由于项目需要,用Flutter重构了之前用Android做过的日历组件,整体效果感觉不错,流畅度甚至超过原来的,这里需要提一下官网的做法,如下:
var date = DateTime.now();
return showDatePicker(
context: context,
initialDate: date,
firstDate: date,
lastDate: date.add(
Duration(days: 30),
),
);
官方的做法就是showDatePicker实现的,支持MD和IOS的风格,但据我了解,只支持单选,不支持开始和结束日期的区间选择,体验也与我需要的效果不一致,所以经过考虑之后,还是决定自己写一个。
先上效果图
实现的功能和需求
- 绘制“日”,“月”,“年”组件,年嵌套多个月,月嵌套多个周,然后再是天
- 绘制日历头部与底部确认选择按钮
- 支持某一天单选,开始日期和结束日期多选,反向选择(先选结束日期再选开始日期),跨月选择,取消选择等事件
- 对外暴露CalendarList组件,这个组件是List类型,也就是说它是多个月的集合
下面分段对部分代码进行描述。
先从调用入口进行分析
下面就是一个日历选择组件的调用方式:
return CalendarList(
firstDate: DateTime(2019, 8),
lastDate: DateTime(2020, 8),
selectedStartDate: DateTime(2019, 8, 28),
selectedEndDate: DateTime(2019, 9, 2),
onSelectFinish: (selectStartTime, selectEndTime) {
List<DateTime> result = <DateTime>[];
result.add(selectStartTime);
if (selectEndTime != null) {
result.add(selectEndTime);
}
Navigator.pop(context, result);
},
);
其中firstDate和lastDate是选择的月份列表,本例中,从2019年8月开始算起,结束时间是2020年8月,然后又有2个参数selectedStartDate和selectedEndDate,这2个参数是给定的默认选中区间,本例中默认选中了2019/8/28和2019/9/2之间的所有日期,默认选中一般是记录用户上次选中的结果。onSelectFinish就是选完之后的回调,以上这些参数是根据实际业务可以灵活设置的。
底部弹出方式的日期方式
这块其实很简单,CalendarList本身就支持从底部滑出,调用的