Flutter日历插件tw_calendar的使用

Flutter日历插件tw_calendar的使用

简介

tw_calendar 是一个简单的日历插件。你可以通过以下链接找到它的详细信息:

安装

pubspec.yaml 文件中添加 tw_calendar 依赖:

dependencies:
  tw_calendar: latest_version

然后在需要使用该插件的文件中导入:

import 'package:tw_calendar/tw_calendar.dart';

开始使用

支持配置类

首先,我们需要定义一些支持配置类来配置日历。

import 'package:flutter/material.dart';

// 选择模式
enum TWCalendarListSelectedMode {
  // 默认: 单选连续,从可选日开始
  singleSerial,
  // 默认选择是连续多选
  doubleSerial,
  // 多选非连续
  notSerial,
}

class TWCalendarConfigs {
  // 日历列表配置对象
  final TWCalendarListConfig? listConfig;

  // 月历配置对象
  final TWCalendarMonthViewConfig? monthViewConfig;

  // 日期配置对象
  final TWCalendarDayNumberConfig? dayNumberConfig;

  // 周视图配置对象
  final TWCalendarWeekdayRowConfig? weekdayRowConfig;
}

/* 列表部分 */
class TWCalendarListConfig {
  // 选择模式
  final TWCalendarListSelectedMode? selectedMode;

  // 水平间隙,默认 8
  final double? horizontalSpace;

  // 确认周视图高度, 默认 66
  final double? ensureViewHeight;

  // 确认按钮的间隙
  final EdgeInsetsGeometry? ensureViewPadding;

  // 确认按钮选中颜色
  final Color? ensureViewSelectedColor;

  // 确认未按钮选中颜色
  final Color? ensureViewUnSelectedColor;

  // 确认按钮字体大小
  final double? ensureTitleFontSize;

  // 确认按钮字体颜色
  final Color? ensureTitleColor;

  // 确定按钮 decoration
  final Decoration? ensureViewDecoration;

  // 最小选择天数
  final int? minSelectDays;

  // 最大选择天数
  final int? maxSelectDays;
}

/* 月历视图部分 */
class TWCalendarMonthViewConfig {
  // 月历标题排序, 默认从周日开始,如是周一开始则偏移量是 1
  final int? sortOffset;

  // 月视图高度,为空则占满剩余空间
  final double? monthBodyHeight;

  // 今天是否可以选择, 默认不支持
  final bool? canSelectedToday;

  // 月份标题
  final List<String>? monthNames;

  // 年标题
  final String? yearTitle;

  // 年月标题字体大小
  final double? titleFontSize;

  // 间隙, 默认 8
  final double? padding;

  // 月历 title 回调
  final String Function(int year, int month)? titleHandler;
}

class TWCalendarDayNumberConfig {
  // 今天颜色
  final Color? todayBackgroundColor;

  // 今天颜色
  final Color? todayTitleColor;

  // 未符合最小或最大选择天数背景颜色
  final Color? minOrMaxSelectedBackgroundColor;

  // 未符合最小或最大选择天数标题颜色
  final Color? minOrMaxSelectedTitleColor;

  // 选择背景颜色
  final Color? selectedBackgroundColor;

  // 选择颜色
  final Color? selectedTitleColor;

  // 选择颜色
  final Color? unSelectedTitleColor;

  // 禁止选择颜色
  final Color? forbidSelectedTitleColor;

  // 间隙
  final double? itemMargin;

  // 字体大小
  final double? fontSize;

  // 今天字体大小
  final double? todayFontSize;

  // 今天标识
  final String? todyTitle;

  // 自定义 widget
  final Widget? Function(
    int year,
    int month,
    int day,
    double size,
    bool isSelected,
    bool isToday,
    bool canSelected,
    bool isMinSelectedDays,
    bool isMaxSelectedDays,
  )? widgetHandler;
}

class TWCalendarWeekdayRowConfig {
  // 周视图高度, 默认 48
  final double? weekDayHeight;

  // 标题颜色
  final Color? titleColor;

  // 标题字体大小
  final double? titleFontSize;

  // 周视图 titles
  final List<String>? titles;
}

示例代码

以下是一个完整的示例代码,展示了如何使用 tw_calendar 插件创建不同的日历视图。

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:tw_calendar/tw_calendar.dart';
import 'package:tw_calendar_example/feature/bidding_day_choice_model.dart';
import 'feature/bidding_calendar_view.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(375, 667),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (BuildContext context, Widget? child) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          debugShowCheckedModeBanner: false,
          home: child,
        );
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text('Calendar Demo'),
        ),
        body: const _HomePage(),
      ),
    );
  }
}

class _HomePage extends StatefulWidget {
  const _HomePage({Key? key}) : super(key: key);

  [@override](/user/override)
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<_HomePage> {
  /// Multiple Serial Date Selected
  _showNavigateMultipleSerialDialog(BuildContext context) {
    showModalBottomSheet(
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
      ),
      context: context,
      builder: (BuildContext context) {
        return const TWCalendarMultipleSerialView();
      },
    );
  }

  /// Multiple NotSerial Date Selected
  _showNavigateMultipleNotSerialDialog(BuildContext context) {
    showModalBottomSheet(
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
      ),
      context: context,
      builder: (BuildContext context) {
        return const TWCalendarMultipleNotSerialView();
      },
    );
  }

  /// Custom Header Widget
  _showNavigateCustomHeaderDialog(BuildContext context) {
    showModalBottomSheet(
      isScrollControlled: true,
      clipBehavior: Clip.hardEdge,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
      ),
      context: context,
      builder: (BuildContext context) {
        return BiddingCalendarView(
          models: [
            BiddingDayChoiceModel(),
            BiddingDayChoiceModel(dayCount: 21),
            BiddingDayChoiceModel(dayCount: 15),
            BiddingDayChoiceModel(dayCount: 7),
            BiddingDayChoiceModel(dayCount: 3),
          ],
          lastDate: TWCalendarTool.nowAfterDays(88),
          selectedStartDate: TWCalendarTool.nowAfterDays(2),
          selectedEndDate: TWCalendarTool.nowAfterDays(10),
          onSelectFinish: (
            selectStartTime,
            selectEndTime,
            notSerialSelectedTimes,
            selectedDays,
          ) {
            print(
                'selectStartTime : $selectStartTime, selectEndTime : $selectEndTime');
            Navigator.pop(context);
          },
          onSelectDayRang: ((selectedDate, selectedDays) {
            print('selectedDate: $selectedDate, selectedDays: $selectedDays');
          }),
        );
      },
    );
  }

  /// Custom Date Widget
  _showNavigateCustomDateDialog(BuildContext context) {
    showModalBottomSheet(
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
      ),
      context: context,
      builder: (BuildContext context) {
        return const TWCalendarCustomDateView();
      },
    );
  }

  /// Limit max or min select days
  _showNavigateLimitMaxOrMinDialog(BuildContext context) {
    showModalBottomSheet(
      isScrollControlled: true,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.only(
          topLeft: Radius.circular(8),
          topRight: Radius.circular(8),
        ),
      ),
      context: context,
      builder: (BuildContext context) {
        return const TWCalendarLimitMaxOrMinView();
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: <Widget>[
          TextButton(
            child: const Text('Calendar: Multiple Serial Date Selected'),
            onPressed: () {
              _showNavigateMultipleSerialDialog(context);
            },
          ),
          TextButton(
            child: const Text('Calendar: Custom Header Widget'),
            onPressed: () {
              _showNavigateCustomHeaderDialog(context);
            },
          ),
          TextButton(
            child: const Text('Calendar: Multiple NotSerial Date Selected'),
            onPressed: () {
              _showNavigateMultipleNotSerialDialog(context);
            },
          ),
          TextButton(
            child: const Text('Calendar: Custom Date Widget'),
            onPressed: () {
              _showNavigateCustomDateDialog(context);
            },
          ),
          TextButton(
            child: const Text(
              'Calendar: Limit Max or Min Selected Days',
              textAlign: TextAlign.center,
            ),
            onPressed: () {
              _showNavigateLimitMaxOrMinDialog(context);
            },
          ),
        ],
      ),
    );
  }
}

class TWCalendarMultipleSerialView extends StatefulWidget {
  const TWCalendarMultipleSerialView({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  TWCalendarMultipleSerialViewState createState() => TWCalendarMultipleSerialViewState();
}

class TWCalendarMultipleSerialViewState extends State<TWCalendarMultipleSerialView> {
  late TWCalendarController controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    controller = TWCalendarController(
      firstDate: TWCalendarTool.today,
      lastDate: TWCalendarTool.nowAfterDays(20),
      selectedStartDate: TWCalendarTool.nowAfterDays(2),
      selectedEndDate: TWCalendarTool.nowAfterDays(10),
      onSelectDayRang: ((selectedDate, selectedDays) {
        print(
            '''onSelectDayRang => selectedDate : $selectedDate, selectedDays : $selectedDays''');
      }),
      onSelectDayTitle: (
        selectStartTime,
        selectEndTime,
        selectedDays,
      ) {
        print(
            'onSelectDayTitle => selectStartTime : $selectStartTime, selectEndTime : $selectEndTime, selectedDays : $selectedDays');
        if (selectStartTime != null && selectEndTime != null) {
          return '''ensure (${selectStartTime.year},${selectStartTime.month},${selectStartTime.day} - ${selectEndTime.year},${selectEndTime.month},${selectEndTime.day})''';
        }
        return "please choice...";
      },
      onSelectFinish: (
        selectStartTime,
        selectEndTime,
        notSerialSelectedTimes,
        selectedDays,
      ) {
        print(
            '''onSelectFinish => selectStartTime : $selectStartTime, selectEndTime : $selectEndTime''');
        Navigator.pop(context);
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return TWCalendarList(
      calendarController: controller,
      configs: TWCalendarConfigs(
        listConfig: TWCalendarListConfig(
          selectedMode: TWCalendarListSelectedMode.doubleSerial,
          ensureViewSelectedColor: Colors.blue,
        ),
        monthViewConfig: TWCalendarMonthViewConfig(
          monthBodyHeight: 300.w,
          canSelectedToday: true,
          sortOffset: 1,
          titleHandler: ((year, month) => '$year - $month'),
        ),
        dayNumberConfig: TWCalendarDayNumberConfig(
          selectedBackgroundColor: Colors.blue,
          todayBackgroundColor: Colors.red,
          todyTitle: 'today',
        ),
        weekdayRowConfig: TWCalendarWeekdayRowConfig(
          titleFontSize: 14.w,
          titleColor: Colors.blue,
          titles: [
            'Mon',
            'Tues',
            'Wed',
            'Thurs',
            'Fri',
            'Satur',
            'Sun',
          ],
        ),
      ),
      headerView: Container(
        alignment: Alignment.center,
        height: 55.w,
        child: Text(
          'Calendar Widget',
          style: TextStyle(
            color: Colors.blue,
            fontSize: 18.w,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

class TWCalendarMultipleNotSerialView extends StatefulWidget {
  const TWCalendarMultipleNotSerialView({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  TWCalendarMultipleNotSerialViewState createState() => TWCalendarMultipleNotSerialViewState();
}

class TWCalendarMultipleNotSerialViewState extends State<TWCalendarMultipleNotSerialView> {
  late TWCalendarController controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    controller = TWCalendarController(
      firstDate: TWCalendarTool.today,
      lastDate: TWCalendarTool.nowAfterDays(33),
      notSerialSelectedDates: [
        TWCalendarTool.nowAfterDays(1),
        TWCalendarTool.nowAfterDays(3),
        TWCalendarTool.nowAfterDays(5),
        TWCalendarTool.nowAfterDays(7),
      ],
      onSelectDayRang: ((selectedDate, selectedDays) {
        print('''onSelectDayRang => onSelectDayRang => 
            selectedDate : $selectedDate, selectedDays : $selectedDays''');
      }),
      onSelectFinish: (selectStartTime, selectEndTime, notSerialSelectedTimes,
          selectedDays) {
        print(
            '''onSelectFinish => onSelectFinish => selectStartTime : $selectStartTime,
             selectEndTime : $selectEndTime, notSerialSelectedTimes: $notSerialSelectedTimes''');
        Navigator.pop(context);
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return TWCalendarList(
      calendarController: controller,
      configs: TWCalendarConfigs(
        listConfig: TWCalendarListConfig(
          selectedMode: TWCalendarListSelectedMode.notSerial,
        ),
        monthViewConfig: TWCalendarMonthViewConfig(
          monthBodyHeight: 300.w,
        ),
      ),
      headerView: Container(
        alignment: Alignment.center,
        height: 55.w,
        child: Text(
          'Multiple Not Serial Date Widget',
          style: TextStyle(
            color: Colors.blue,
            fontSize: 18.w,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

class TWCalendarCustomDateView extends StatefulWidget {
  const TWCalendarCustomDateView({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  TWCalendarCustomDateViewState createState() => TWCalendarCustomDateViewState();
}

class TWCalendarCustomDateViewState extends State<TWCalendarCustomDateView> {
  late TWCalendarController controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    controller = TWCalendarController(
      firstDate: TWCalendarTool.today,
      lastDate: TWCalendarTool.nowAfterDays(33),
      onSelectDayRang: ((selectedDate, selectedDays) {
        print('''onSelectDayRang => onSelectDayRang => 
            selectedDate : $selectedDate, selectedDays : $selectedDays''');
      }),
      onSelectFinish: (selectStartTime, selectEndTime, notSerialSelectedTimes,
          selectedDays) {
        print(
          '''onSelectFinish => onSelectFinish => selectStartTime : $selectStartTime
          , selectEndTime : $selectEndTime, notSerialSelectedTimes: $notSerialSelectedTimes''',
        );
        Navigator.pop(context);
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return TWCalendarList(
      calendarController: controller,
      configs: TWCalendarConfigs(
        listConfig: TWCalendarListConfig(
          selectedMode: TWCalendarListSelectedMode.notSerial,
        ),
        monthViewConfig: TWCalendarMonthViewConfig(
          monthBodyHeight: 300.w,
        ),
        dayNumberConfig: TWCalendarDayNumberConfig(
          widgetHandler: (
            year,
            month,
            day,
            size,
            isSelected,
            isToday,
            canSelected,
            isMinSelectedDays,
            isMaxSelectedDays,
          ) {
            bool tomorrow = TWCalendarTool.isSameDate(
              TWCalendarTool.tomorrow,
              DateTime(year, month, day),
            );
            return SizedBox(
              width: size,
              height: size,
              child: Container(
                alignment: Alignment.center,
                margin: const EdgeInsets.all(4),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(4),
                  color: canSelected
                      ? (isSelected
                          ? Colors.orange.withOpacity(0.3)
                          : Colors.black.withOpacity(0.1))
                      : Colors.white,
                ),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      tomorrow ? '明天' : (isToday ? '今天' : '$day'),
                      textAlign: TextAlign.center,
                      style: TextStyle(
                        color: canSelected
                            ? (isSelected ? Colors.red : Colors.black)
                            : Colors.grey,
                      ),
                    ),
                    if (tomorrow && canSelected)
                      Container(
                        height: 10,
                        width: 10,
                        decoration: BoxDecoration(
                          color: (isSelected ? Colors.red : Colors.black),
                          borderRadius: BorderRadius.circular(5),
                        ),
                      )
                    else
                      Icon(
                        Icons.favorite,
                        color: (isSelected ? Colors.pink : Colors.black),
                        size: 10.0,
                      )
                  ],
                ),
              ),
            );
          },
        ),
      ),
      headerView: Container(
        alignment: Alignment.center,
        height: 55.w,
        child: Text(
          'Calendar Custom Date Widget',
          style: TextStyle(
            color: Colors.blue,
            fontSize: 18.w,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

class TWCalendarLimitMaxOrMinView extends StatefulWidget {
  const TWCalendarLimitMaxOrMinView({
    Key? key,
  }) : super(key: key);

  [@override](/user/override)
  TWCalendarLimitMaxOrMinViewState createState() => TWCalendarLimitMaxOrMinViewState();
}

class TWCalendarLimitMaxOrMinViewState extends State<TWCalendarLimitMaxOrMinView> {
  late TWCalendarController controller;

  final int minSelectedDays = 3;
  final int maxSelectedDays = 5;

  [@override](/user/override)
  void initState() {
    super.initState();
    controller = TWCalendarController(
      firstDate: TWCalendarTool.today,
      lastDate: TWCalendarTool.nowAfterDays(50),
      onSelectDayRang: ((selectedDate, selectedDays) {
        print(
            '''onSelectDayRang => selectedDate : $selectedDate, selectedDays : $selectedDays''');
      }),
      onSelectDayTitle: (
        selectStartTime,
        selectEndTime,
        selectedDays,
      ) {
        print(
            'onSelectDayTitle => selectStartTime : $selectStartTime, selectEndTime : $selectEndTime, selectedDays : $selectedDays');
        if (selectStartTime != null && selectEndTime != null) {
          return '''ensure (${selectStartTime.year},${selectStartTime.month},${selectStartTime.day} - ${selectEndTime.year},${selectEndTime.month},${selectEndTime.day})''';
        }
        return "please choice...";
      },
      onSelectFinish: (
        selectStartTime,
        selectEndTime,
        notSerialSelectedTimes,
        selectedDays,
      ) {
        print(
            '''onSelectFinish => selectStartTime : $selectStartTime, selectEndTime : $selectEndTime''');
        if (selectedDays > maxSelectedDays || selectedDays < minSelectedDays) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(
              content: Text(
                'Please select $minSelectedDays to $maxSelectedDays days',
              ),
              duration: const Duration(seconds: 2),
              behavior: SnackBarBehavior.floating,
            ),
          );
        }
        Navigator.pop(context);
      },
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return TWCalendarList(
      calendarController: controller,
      configs: TWCalendarConfigs(
        listConfig: TWCalendarListConfig(
          selectedMode: TWCalendarListSelectedMode.doubleSerial,
          minSelectDays: minSelectedDays,
          maxSelectDays: maxSelectedDays,
        ),
        monthViewConfig: TWCalendarMonthViewConfig(
          monthBodyHeight: 300.w,
          canSelectedToday: true,
          sortOffset: 1,
          titleHandler: ((year, month) => '$year - $month'),
        ),
      ),
      headerView: Container(
        alignment: Alignment.center,
        height: 55.w,
        child: Text(
          'Calendar Widget',
          style: TextStyle(
            color: Colors.orange,
            fontSize: 18.w,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

更多关于Flutter日历插件tw_calendar的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter日历插件tw_calendar的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用tw_calendar插件的一个基本示例。这个插件提供了一个高度可定制的日历组件,可以用于显示和选择日期。

首先,确保你已经在pubspec.yaml文件中添加了tw_calendar依赖:

dependencies:
  flutter:
    sdk: flutter
  tw_calendar: ^x.y.z  # 请将x.y.z替换为当前最新版本号

然后,运行flutter pub get来安装依赖。

接下来,是一个简单的使用tw_calendar的示例代码:

import 'package:flutter/material.dart';
import 'package:tw_calendar/tw_calendar.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Calendar Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: CalendarScreen(),
    );
  }
}

class CalendarScreen extends StatefulWidget {
  @override
  _CalendarScreenState createState() => _CalendarScreenState();
}

class _CalendarScreenState extends State<CalendarScreen> {
  DateTime? selectedDate;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Calendar Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              'Selected Date: ${selectedDate != null ? selectedDate!.toLocal() : 'None'}',
              style: TextStyle(fontSize: 18),
            ),
            SizedBox(height: 20),
            Expanded(
              child: TWCalendar(
                selectedDate: selectedDate,
                onDateSelected: (DateTime date) {
                  setState(() {
                    selectedDate = date;
                  });
                },
                // 自定义日历样式
                calendarStyle: TWCalendarStyle(
                  todayTextStyle: TextStyle(color: Colors.red),
                  selectedTextStyle: TextStyle(color: Colors.blue, fontSize: 18, fontWeight: FontWeight.bold),
                  weekendTextStyle: TextStyle(color: Colors.grey),
                  weekdayTextStyle: TextStyle(color: Colors.black),
                  headerStyle: TWCalendarHeaderStyle(
                    backgroundColor: Colors.blue,
                    textStyle: TextStyle(color: Colors.white),
                  ),
                ),
                // 自定义日历构建器
                builder: (context, date, isToday, isSelected) {
                  return Container(
                    decoration: BoxDecoration(
                      color: isSelected ? Colors.blue.withOpacity(0.1) : null,
                      borderRadius: BorderRadius.circular(8),
                    ),
                    child: Center(
                      child: Text(
                        date.day.toString(),
                        style: TextStyle(
                          color: isToday ? Colors.red : Colors.black,
                          fontSize: isSelected ? 18 : 16,
                        ),
                      ),
                    ),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

代码解释:

  1. 依赖添加:在pubspec.yaml中添加tw_calendar依赖。
  2. 主应用MyApp是一个简单的Material应用,它定义了应用的主题和主页。
  3. 日历屏幕CalendarScreen是一个有状态的Widget,用于管理日历的显示和交互。
  4. 日历组件TWCalendar组件被放置在Expanded中,使其占据剩余空间。
  5. 日期选择回调:通过onDateSelected回调,当用户选择日期时更新selectedDate状态。
  6. 自定义样式:使用calendarStylebuilder参数来自定义日历的显示样式。

这个示例展示了如何使用tw_calendar插件创建一个基本的日历界面,并允许用户选择日期。你可以根据需要进一步自定义和扩展这个示例。

回到顶部