内容简介:最近自己写了个demo,用到了日历方面的东西,然后实现来一下,最后打算封装一下,以后可以直接拿来使用。参考了Android的一个开源日历库Flutter日历的项目地址:
最近自己写了个demo,用到了日历方面的东西,然后实现来一下,最后打算封装一下,以后可以直接拿来使用。
参考了Android的一个开源日历库 github.com/huanghaibin… ,实现思路其实差不多,都是可以利用canvas将日历给画出来。
Flutter日历的项目地址: github.com/LXD31256949…
示例
Flutter上的一个日历控件,可以定制成自己想要的样子。
主要功能
- 支持公历,农历,节气,传统节日,常用节假日
- 日期范围设置,默认支持的最大日期范围为1971.01-2055.12
- 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰
- 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。
- 跳转到指定日期,默认支持动画切换
- 自定义日历Item,支持组合widget的方式和利用canvas绘制的方式
- 自定义顶部的WeekBar
- 可以给Item添加自定义的额外数据,实现各种额外的功能。比如实现进度条风格的日历
使用
在pubspec.yaml添加依赖:
flutter_custom_calendar: git: url: https://github.com/LXD312569496/flutter_custom_calendar.git 复制代码
引入flutter_custom_calendar,就可以使用CalendarViewWidget,配置CalendarController就可以了。
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; CalendarViewWidget({@required this.calendarController, this.boxDecoration}); 复制代码
- boxDecoration用来配置整体的背景
- 利用CalendarController来配置一些数据,并且可以通过CalendarController进行一些操作或者事件监听,比如滚动到下一个月,获取当前被选中的Item等等。
下面是CalendarController中一些支持自定义配置的属性。不配置的话,会有对应的默认值。
//默认是单选,可以配置为MODE_SINGLE_SELECT,MODE_MULTI_SELECT int selectMode; //日历显示的最小年份和最大年份 int minYear; int maxYear; //日历显示的最小年份的月份,最大年份的月份 int minYearMonth; int maxYearMonth; //日历显示的当前的年份和月份 int nowYear; int nowMonth; //可操作的范围设置,比如点击选择 int minSelectYear; int minSelectMonth; int minSelectDay; int maxSelectYear; int maxSelectMonth; int maxSelectDay; //注意:不能超过对应月份的总天数 Set<DateModel> selectedDateList = new Set(); //被选中的日期,用于多选 DateModel selectDateModel; //当前选择项,用于单选 int maxMultiSelectCount; //多选,最多选多少个 Map<DateTime, Object> extraDataMap = new Map(); //自定义额外的数据 //各种事件回调 OnMonthChange monthChange; //月份切换事件 OnCalendarSelect calendarSelect; //点击选择事件 OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围 OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数 //支持自定义绘制 DayWidgetBuilder dayWidgetBuilder; //创建日历item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar //构造函数 CalendarController( {int selectMode = Constants.MODE_SINGLE_SELECT, DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget, WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget, int minYear = 1971, int maxYear = 2055, int minYearMonth = 1, int maxYearMonth = 12, int nowYear = -1, int nowMonth = -1, int minSelectYear = 1971, int minSelectMonth = 1, int minSelectDay = 1, int maxSelectYear = 2055, int maxSelectMonth = 12, int maxSelectDay = 30, Set<DateTime> selectedDateTimeList = EMPTY_SET, DateModel selectDateModel, int maxMultiSelectCount = 9999, Map<DateTime, Object> extraDataMap = EMPTY_MAP}) 复制代码
利用controller添加监听事件
比如月份切换事件、点击选择事件。
//月份切换监听 void addMonthChangeListener(OnMonthChange listener) { this.monthChange = listener; } //点击选择监听 void addOnCalendarSelectListener(OnCalendarSelect listener) { this.calendarSelect = listener; } //多选超出指定范围 void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) { this.multiSelectOutOfRange = listener; } //多选超出限制个数 void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) { this.multiSelectOutOfSize = listener; } 复制代码
利用controller来控制日历的切换,支持配置动画
//跳转到指定日期 void moveToCalendar(int year, int month, int day, {bool needAnimation = false, Duration duration = const Duration(milliseconds: 500), Curve curve = Curves.ease}); //切换到下一年 void moveToNextYear(); //切换到上一年 void moveToPreviousYear(); //切换到下一个月份, void moveToNextMonth(); //切换到上一个月份 void moveToPreviousMonth(); 复制代码
利用controller来获取日历的一些数据信息
// 获取当前的月份 DateTime getCurrentMonth(); //获取被选中的日期,多选 Set<DateModel> getMultiSelectCalendar(); //获取被选中的日期,单选 DateModel getSingleSelectCalendar(); 复制代码
自定义UI
包括自定义WeekBar、自定义日历Item,默认使用的都是DefaultXXXWidget。
只要继承对应的Base类,实现相应的方法,然后只需要在配置Controller的时候,实现相应的Builder方法就可以了。
//支持自定义绘制 DayWidgetBuilder dayWidgetBuilder; //创建日历item WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //创建顶部的weekbar 复制代码
自定义WeekBar
继承BaseWeekBar,重写getWeekBarItem(index)方法就可以。随便你怎么实现,只需要返回一个Widget就可以了。
class DefaultWeekBar extends BaseWeekBar { const DefaultWeekBar({Key key}) : super(key: key); @override Widget getWeekBarItem(int index) { /** * 自定义Widget */ return new Container( height: 40, alignment: Alignment.center, child: new Text( Constants.WEEK_LIST[index], style: topWeekTextStyle, ), ); } } 复制代码
自定义日历Item:
提供两种方法,一种是利用组合widget的方式来创建,一种是利用Canvas来自定义绘制Item。最后只需要在CalendarController的构造参数中进行配置就可以了。
- 继承BaseCombineDayWidget,重写getNormalWidget(DateModel dateModel) 和getSelectedWidget(DateModel dateModel)就可以了,返回对应的widget就行。
class DefaultCombineDayWidget extends BaseCombineDayWidget { DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); @override Widget getNormalWidget(DateModel dateModel) { //实现默认状态下的UI } @override Widget getSelectedWidget(DateModel dateModel) { //绘制被选中的UI } } 复制代码
- 继承BaseCustomDayWidget,重写drawNormal和drawSelected的两个方法就可以了,利用canvas自己绘制Item。
class DefaultCustomDayWidget extends BaseCustomDayWidget { DefaultCustomDayWidget(DateModel dateModel) : super(dateModel); @override void drawNormal(DateModel dateModel, Canvas canvas, Size size) { //实现默认状态下的UI defaultDrawNormal(dateModel, canvas, size); } @override void drawSelected(DateModel dateModel, Canvas canvas, Size size) { //绘制被选中的UI defaultDrawSelected(dateModel, canvas, size); } } 复制代码
DateModel实体类
日历所用的日期的实体类DateModel,有下面这些属性。
/** * 日期的实体类 */ class DateModel { int year; int month; int day = 1; int lunarYear; int lunarMonth; int lunarDay; String lunarString; //农历字符串 String solarTerm; //24节气 String gregorianFestival; //公历节日 String traditionFestival; //传统农历节日 bool isCurrentDay; //是否是今天 bool isLeapYear; //是否是闰年 bool isWeekend; //是否是周末 int leapMonth; //是否是闰月 Object extraData; //自定义的额外数据 bool isInRange = false; //是否在范围内,比如可以实现在某个范围外,设置置灰的功能 bool isSelected; //是否被选中,用来实现一些标记或者选择功能 @override String toString() { return 'DateModel{year: $year, month: $month, day: $day}'; } //如果是闰月,则返回闰月 //转化成DateTime格式 DateTime getDateTime() { return new DateTime(year, month, day); } //根据DateTime创建对应的model,并初始化农历和传统节日等信息 static DateModel fromDateTime(DateTime dateTime) { DateModel dateModel = new DateModel() ..year = dateTime.year ..month = dateTime.month ..day = dateTime.day; LunarUtil.setupLunarCalendar(dateModel); return dateModel; } @override bool operator ==(Object other) => identical(this, other) || other is DateModel && runtimeType == other.runtimeType && year == other.year && month == other.month && day == other.day; @override int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode; } 复制代码
TODO LIST
- 优化代码实现
- 支持屏蔽指定的某些天
- 继续写几个不同风格的Demo
- 支持周视图
- 支持动画切换周视图和月视图
以上所述就是小编给大家介绍的《Flutter日历,可以自定义风格UI》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- vue日历组件
- 原生JavaScript实现造日历轮子
- 第二章 使用VUX建立日历
- uiw 1.4.0 发布,新增日历控件
- uiw 1.4.3 发布,增强日历控件
- 日程日历系统,顶级插件FullCalendar使用说明
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。