用 Flutter 做一个更顺手的日历组件:calendarview_flutter

用 Flutter 做一个更顺手的日历组件:calendarview_flutter

做 App 的时候,日历组件经常看起来只是一个"小控件",但真正落到业务里会很快变复杂:单选、范围选择、多选、周/月切换、禁用日期、标记点、年视图、内容列表联动、不同业务视觉样式......如果每个项目都从零写一套,后期维护成本会非常高。

所以我整理并开源了一个 Flutter 日历组件:calendarview_flutter。它的目标不是只提供一个固定样式的日期选择器,而是把日历状态、交互能力和 UI 构建协议拆开,让业务可以更轻松地组合出自己的日历体验。

项目地址:github.com/raintang666...

它适合解决什么问题?

如果你的业务里有下面这些需求,应该会比较适合:

  • 需要单选、范围选择、多选等不同日期选择模式
  • 需要月视图和周视图切换
  • 需要限制可选日期范围,比如只能选择未来 90 天
  • 需要禁用部分日期,比如节假日、不可预约日期、已满日期
  • 需要给日期添加标记,比如日程、小红点、状态标签
  • 需要日历和内容列表联动
  • 需要自定义日历单元格 UI,而不是被固定样式绑死

组件内部把核心状态放在 CalendarController 里,视图层通过 CalendarViewCalendarInteractiveViewCalendarMonthYearView 等组件来承载不同场景。这样业务代码可以更明确地控制状态,也更容易替换 UI。

快速接入

在项目中添加依赖:

yaml 复制代码
dependencies:
  calendarview_flutter: ^0.1.0

然后导入:

dart 复制代码
import 'package:calendarview_flutter/calendarview_flutter.dart';

一个最小示例大概是这样:

dart 复制代码
final controller = CalendarController(focusedDay: DateTime.now());

CalendarView(
  controller: controller,
  pageOrientation: CalendarPageOrientation.horizontal,
  onDaySelected: (day) {
    controller.selectDay(day);
  },
)

这段代码里,CalendarController 负责保存当前聚焦日期、选中状态、选择模式、日期边界、标记数据等信息;CalendarView 负责展示和响应用户交互。

三种常见选择模式

日历选择是很多业务的核心。calendarview_flutter 目前支持单选、范围选择和多选。

单选适合生日、预约日期、签到日期等场景:

dart 复制代码
controller
  ..setSelectionMode(CalendarSelectionMode.single)
  ..selectDay(DateTime(2026, 7, 14));

范围选择适合酒店入住、请假、周期筛选等场景:

dart 复制代码
controller
  ..setSelectionMode(CalendarSelectionMode.range)
  ..setRangeSelectionLimits(minRange: 2, maxRange: 14);

CalendarView(
  controller: controller,
  pageOrientation: CalendarPageOrientation.horizontal,
  onDaySelected: (day) => controller.selectDay(day),
  onRangeSelected: (range) {
    final start = range.start;
    final end = range.end;
  },
  onSelectOutOfRange: (day, violation) {},
)

多选适合打卡、排班、批量选择日期等场景:

dart 复制代码
controller
  ..setSelectionMode(CalendarSelectionMode.multi)
  ..setMaxMultiSelectSize(5);

CalendarView(
  controller: controller,
  pageOrientation: CalendarPageOrientation.horizontal,
  onDaySelected: (day) => controller.selectDay(day),
  onMultiSelected: (day, selectedSize, maxSize) {},
  onMultiSelectOutOfSize: (day, maxSize) {},
)

日期边界、禁用日期和标记

实际业务里,日历通常不是"所有日期都能点"。比如预约系统可能只能选择某个时间范围内的日期,票务系统可能要禁用售罄日期,日程系统则需要在某些日期上显示标记。

这些能力可以通过 controller 配置:

dart 复制代码
controller
  ..setCalendarRange(
    minDate: DateTime(2026, 7, 1),
    maxDate: DateTime(2026, 12, 31),
  )
  ..setDisabledDatePredicate((day) {
    return day.weekday == DateTime.sunday;
  })
  ..setMarkers({
    DateTime(2026, 7, 15): [
      CalendarMarker(label: '会议', color: Colors.blue),
    ],
  });

这种方式的好处是:选择逻辑、日期限制和 UI 表现不需要混在一起。业务可以先把规则交给 controller,再由视图决定如何展示。

可展开、可折叠、可联动

除了基础月历,项目里还提供了 CalendarInteractiveView,用于处理更接近真实 App 的日历交互,比如:

  • 月视图和周视图切换
  • 日历折叠和展开
  • 全屏展开
  • 日历和内容列表联动
  • 内容区纵向拖拽锁定

如果你的页面上方是日历,下方是对应日期的内容列表,这类结构就很适合用 CalendarInteractiveView 来承载。

年视图和自定义样式

很多日历组件做到月视图就结束了,但在需要快速跨月份跳转的场景里,年视图会非常有用。项目提供了 CalendarMonthYearViewCalendarMonthYearController,可以在日历上增加年视图能力。

同时,样式层并没有被写死。库里提供了 CalendarComponentBuilder 协议,业务可以自己实现星期栏、日期单元格、月份头等 UI:

dart 复制代码
class MyCalendarBuilder extends CalendarComponentBuilder {
  const MyCalendarBuilder();

  @override
  List<String> orderedWeekLabels(int firstWeekday) {
    return calendarOrderedWeekLabels(
      const ['日', '一', '二', '三', '四', '五', '六'],
      firstWeekday,
    );
  }

  @override
  Widget buildWeekBarCell(BuildContext context, CalendarWeekBarCellData data) {
    return Text(data.label);
  }

  @override
  Widget buildDayCell(BuildContext context, CalendarDayCellData data) {
    return Center(child: Text('${data.date.day}'));
  }
}

也就是说,组件提供的是"日历能力"和"扩展协议",具体长什么样,可以交给业务决定。

最后

calendarview_flutter 目前还在持续完善中,欢迎大家试用、提 issue 或一起交流改进。后面我也会继续补充更多 demo、优化交互细节,并把实际业务里常见的日历场景沉淀到组件里。

GitHub 地址:github.com/raintang666...

如果这个项目刚好帮你省下一点时间,也欢迎点个 Star 支持一下。

相关推荐
一枚菜鸟_3 小时前
Flutter + Cursor 一天出 App?这 3 个坑让开发者多花了 3 小时
flutter·cursor
心中有国也有家8 小时前
AtomGit Flutter 鸿蒙客户端:零外部资源的应用打包策略
android·javascript·flutter·华为·harmonyos
心中有国也有家8 小时前
AtomGit Flutter 鸿蒙客户端:为 E-Brufen 注入情感节律的文案设计哲学
javascript·学习·flutter·华为·harmonyos
恋猫de小郭8 小时前
Fluter 共享内存多线程正在落地,IsolateGroupBound 来了
android·前端·flutter
太子釢1 天前
Flutter 与 Native 混合开发策略调研与方案对比
flutter
西西学代码1 天前
Flutter---Stack
flutter
ZZZMMM.zip1 天前
基于鸿蒙PC与鸿蒙Flutter框架构建AI本地生活服务平台
人工智能·flutter·华为·harmonyos·鸿蒙
木叶丸1 天前
AI 编程概念与 Harness 工程实践入门
人工智能·flutter·ios
程序员老刘2 天前
腾讯混元Hy3在Flutter项目中的实战体验
flutter·ai编程