From 004916810435a89725899a9933086d8b91ca6ce5 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Mon, 4 Nov 2019 16:04:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E9=80=89=E6=A8=A1=E5=BC=8Fbug?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9A=E8=B6=85=E8=BF=87=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E4=B8=AA=E6=95=B0=E5=90=8E=EF=BC=8C=E6=8A=A5=E9=94=99=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=20=E5=A4=9A=E9=80=89=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E6=97=A0=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/multi_select_style_page.dart | 5 +- lib/calendar_provider.dart | 25 ++++--- lib/configuration.dart | 8 ++- lib/controller.dart | 87 +++++++++++++++--------- lib/widget/calendar_view.dart | 1 + lib/widget/month_view.dart | 55 +++++++-------- lib/widget/week_view.dart | 29 ++++---- 7 files changed, 121 insertions(+), 89 deletions(-) diff --git a/example/lib/multi_select_style_page.dart b/example/lib/multi_select_style_page.dart index 0fa32ed..d86b06e 100644 --- a/example/lib/multi_select_style_page.dart +++ b/example/lib/multi_select_style_page.dart @@ -28,6 +28,9 @@ class _MultiSelectStylePageState extends State { minSelectYear: 2019, minSelectMonth: 5, minSelectDay: 20, + selectedDateTimeList: { + DateTime.now(), + } ); controller.addMonthChangeListener( @@ -45,7 +48,7 @@ class _MultiSelectStylePageState extends State { text = new ValueNotifier("${DateTime.now().year}年${DateTime.now().month}月"); selectText = new ValueNotifier( - "多选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); + "多选模式\n选中的时间:\n${controller.getMultiSelectCalendar().join("\n")}"); } @override diff --git a/lib/calendar_provider.dart b/lib/calendar_provider.dart index a4db0c1..90b426c 100644 --- a/lib/calendar_provider.dart +++ b/lib/calendar_provider.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/cache_data.dart'; import 'package:flutter_custom_calendar/configuration.dart'; @@ -15,7 +17,7 @@ import 'package:flutter_custom_calendar/widget/month_view.dart'; */ class CalendarProvider extends ChangeNotifier { double _totalHeight; //当前月视图的整体高度 - Set selectedDateList = new Set(); //被选中的日期,用于多选 + HashSet selectedDateList = new HashSet(); //被选中的日期,用于多选 DateModel _selectDateModel; //当前选中的日期,用于单选 ItemContainerState lastClickItemState; DateModel _lastClickDateModel; @@ -117,17 +119,20 @@ class CalendarProvider extends ChangeNotifier { WeekBarItemWidgetBuilder weekBarItemWidgetBuilder, }) { LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider initData"); - if (selectedDateList != null) { - this.selectedDateList.addAll(selectedDateList); - } - this.selectDateModel = selectDateModel; this.calendarConfiguration = calendarConfiguration; + print( + "calendarConfiguration.defaultSelectedDateList:${calendarConfiguration.defaultSelectedDateList}"); + this + .selectedDateList + .addAll(this.calendarConfiguration.defaultSelectedDateList); + this.selectDateModel = this.calendarConfiguration.selectDateModel; this.calendarConfiguration.padding = padding; this.calendarConfiguration.margin = margin; this.calendarConfiguration.itemSize = itemSize; this.calendarConfiguration.verticalSpacing = verticalSpacing; - this.calendarConfiguration.dayWidgetBuilder=dayWidgetBuilder; - this.calendarConfiguration.weekBarItemWidgetBuilder=weekBarItemWidgetBuilder; + this.calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder; + this.calendarConfiguration.weekBarItemWidgetBuilder = + weekBarItemWidgetBuilder; //lastClickDateModel,默认是选中的item,如果为空的话,默认是当前的时间 this.lastClickDateModel = selectDateModel != null @@ -149,8 +154,8 @@ class CalendarProvider extends ChangeNotifier { MediaQueryData.fromWindow(WidgetsBinding.instance.window); if (mediaQueryData.orientation == Orientation.landscape) { calendarConfiguration.itemSize = (mediaQueryData.size.height - - calendarConfiguration.padding.horizontal - - calendarConfiguration.margin.horizontal) / + calendarConfiguration.padding.vertical - + calendarConfiguration.margin.vertical) / 7; } else { calendarConfiguration.itemSize = (mediaQueryData.size.width - @@ -171,8 +176,6 @@ class CalendarProvider extends ChangeNotifier { calendarConfiguration.nowYear, calendarConfiguration.nowMonth); totalHeight = calendarConfiguration.itemSize * (lineCount) + calendarConfiguration.verticalSpacing * (lineCount - 1); - print( - "1111111:totalHeight:$totalHeight,lineCount:$lineCount,calendarConfiguration.nowYear:${calendarConfiguration.nowYear},calendarConfiguration.nowMonth:${calendarConfiguration.nowMonth}"); } else { totalHeight = calendarConfiguration.itemSize; } diff --git a/lib/configuration.dart b/lib/configuration.dart index 2047d50..3bed95a 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/model/date_model.dart'; @@ -34,7 +36,8 @@ class CalendarConfiguration { int maxSelectMonth; int maxSelectDay; //注意:不能超过对应月份的总天数 - Set defaultSelectedDateList = new Set(); //默认被选中的日期 + DateModel selectDateModel; //默认被选中的item,用于单选 + HashSet defaultSelectedDateList; //默认被选中的日期set,用于多选 int maxMultiSelectCount; //多选,最多选多少个 Map extraDataMap = new Map(); //自定义额外的数据 @@ -70,6 +73,8 @@ class CalendarConfiguration { List weekList = new List(); //星期list PageController monthController; //月份的controller PageController weekController; //星期的controller + DateModel minSelectDate; + DateModel maxSelectDate; CalendarConfiguration( {this.selectMode, @@ -86,6 +91,7 @@ class CalendarConfiguration { this.maxSelectMonth, this.maxSelectDay, this.defaultSelectedDateList, + this.selectDateModel, this.maxMultiSelectCount, this.extraDataMap, this.monthList, diff --git a/lib/controller.dart b/lib/controller.dart index c52c276..2a71fb9 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -1,3 +1,5 @@ +import 'dart:collection'; + import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/configuration.dart'; @@ -45,8 +47,8 @@ class CalendarController { int maxSelectYear = 2055, int maxSelectMonth = 12, int maxSelectDay = 30, - Set selectedDateTimeList = EMPTY_SET, - DateModel selectDateModel, + Set selectedDateTimeList = EMPTY_SET, //多选模式下,默认选中的item列表 + DateModel selectDateModel, //单选模式下,默认选中的item int maxMultiSelectCount = 9999, Map extraDataMap = EMPTY_MAP}) { LogUtil.log(TAG: this.runtimeType, message: "init CalendarConfiguration"); @@ -58,29 +60,41 @@ class CalendarController { nowMonth = DateTime.now().month; } calendarConfiguration = CalendarConfiguration( - selectMode: selectMode, - showMode: showMode, - minYear: minYear, - maxYear: maxYear, - maxYearMonth: maxYearMonth, - nowYear: nowYear, - nowMonth: nowMonth, - minSelectYear: minSelectYear, - minSelectMonth: minSelectMonth, - minYearMonth: minYearMonth, - minSelectDay: minSelectDay, - maxSelectYear: maxSelectYear, - maxSelectMonth: maxSelectMonth, - extraDataMap: extraDataMap, - maxSelectDay: maxSelectDay, - ); - - if (selectedDateTimeList != null && selectedDateTimeList.isNotEmpty) { - calendarConfiguration.defaultSelectedDateList - .addAll(selectedDateTimeList.map((dateTime) { - return DateModel.fromDateTime(dateTime); - }).toSet()); - } + selectMode: selectMode, + showMode: showMode, + minYear: minYear, + maxYear: maxYear, + maxYearMonth: maxYearMonth, + nowYear: nowYear, + nowMonth: nowMonth, + minSelectYear: minSelectYear, + minSelectMonth: minSelectMonth, + minYearMonth: minYearMonth, + minSelectDay: minSelectDay, + maxSelectYear: maxSelectYear, + maxSelectMonth: maxSelectMonth, + extraDataMap: extraDataMap, + maxSelectDay: maxSelectDay, + maxMultiSelectCount: maxMultiSelectCount, + selectDateModel: selectDateModel); + + calendarConfiguration.defaultSelectedDateList = new HashSet(); + calendarConfiguration.defaultSelectedDateList + .addAll(selectedDateTimeList.map((dateTime) { + return DateModel.fromDateTime(dateTime); + }).toSet()); + //将默认选中的数据,放到provider中 + calendarProvider.selectDateModel = selectDateModel; + calendarProvider.selectedDateList = + calendarConfiguration.defaultSelectedDateList; + calendarConfiguration.minSelectDate = DateModel.fromDateTime(DateTime( + calendarConfiguration.minSelectYear, + calendarConfiguration.minSelectMonth, + calendarConfiguration.minSelectDay)); + calendarConfiguration.maxSelectDate = DateModel.fromDateTime(DateTime( + calendarConfiguration.maxSelectYear, + calendarConfiguration.maxSelectMonth, + calendarConfiguration.maxSelectDay)); LogUtil.log( TAG: this.runtimeType, @@ -109,11 +123,6 @@ class CalendarController { dateModel.year = i; dateModel.month = j; - //如果没有配置当前时间,设置成当前的时间 - if (nowYear == -1 || nowMonth == -1) { - nowYear = DateTime.now().year; - nowMonth = DateTime.now().month; - } if (i == nowYear && j == nowMonth) { initialPage = nowMonthIndex; } @@ -127,14 +136,13 @@ class CalendarController { LogUtil.log( TAG: this.runtimeType, message: - "初始化月份视图的信息:一共有${monthList.length}个月,initialPage为${nowMonthIndex}"); + "初始化月份视图的信息:一共有${monthList.length}个月,initialPage为$nowMonthIndex"); } if (showMode != CalendarConstants.MODE_SHOW_ONLY_MONTH) { //计算一共多少周 //计算方法:第一天是周几,最后一天是周几,中间的天数/7后加上2就是结果了 int initialWeekPage = 0; - int nowWeekIndex = 0; weekList.clear(); //如果没有配置当前时间,设置成当前的时间 if (nowYear == -1 || nowMonth == -1) { @@ -166,7 +174,7 @@ class CalendarController { LogUtil.log( TAG: this.runtimeType, message: - "初始化星期视图的信息:一共有${weekList.length}个星期,initialPage为${initialWeekPage}"); + "初始化星期视图的信息:一共有${weekList.length}个星期,initialPage为$initialWeekPage"); this.weekController = new PageController(initialPage: initialWeekPage); } @@ -218,6 +226,19 @@ class CalendarController { this.calendarProvider.generation.value++; } + //可以动态修改默认选中的item。 + void changeDefaultSelectedDateList(Set defaultSelectedDateList) { + this.calendarConfiguration.defaultSelectedDateList = + defaultSelectedDateList; + this.calendarProvider.generation.value++; + } + + //可以动态修改默认选中的item + void changeDefaultSelectedDateModel(DateModel dateModel) { + this.calendarProvider.selectDateModel = dateModel; + this.calendarProvider.generation.value++; + } + /** * 月份或者星期的上一页 */ diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index cc73ad0..6227a64 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -28,6 +28,7 @@ class CalendarViewWidget extends StatefulWidget { //日历item之间的竖直方向间距,默认10 final double verticalSpacing; + //自定义日历item final DayWidgetBuilder dayWidgetBuilder; final WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 876a029..2d89aa8 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -36,27 +36,11 @@ class _MonthViewState extends State List items = List(); int lineCount; - -// double itemHeight; -// double totalHeight; -// double mainSpacing = 10; - - DateModel minSelectDate; - DateModel maxSelectDate; Map extraDataMap; //自定义额外的数据 @override void initState() { super.initState(); - - minSelectDate = DateModel.fromDateTime(DateTime( - widget.configuration.minSelectYear, - widget.configuration.minSelectMonth, - widget.configuration.minSelectDay)); - maxSelectDate = DateModel.fromDateTime(DateTime( - widget.configuration.maxSelectYear, - widget.configuration.maxSelectMonth, - widget.configuration.maxSelectDay)); extraDataMap = widget.configuration.extraDataMap; DateModel firstDayOfMonth = @@ -73,12 +57,12 @@ class _MonthViewState extends State lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); - //第一帧后 + //第一帧后,添加监听,generation发生变化后,需要刷新整个日历 WidgetsBinding.instance.addPostFrameCallback((callback) { Provider.of(context, listen: false) .generation .addListener(() async { - extraDataMap={}; + extraDataMap = widget.configuration.extraDataMap; await getItems(); }); }); @@ -88,8 +72,8 @@ class _MonthViewState extends State items = await compute(initCalendarForMonthView, { 'year': widget.year, 'month': widget.month, - 'minSelectDate': minSelectDate, - 'maxSelectDate': maxSelectDate, + 'minSelectDate': widget.configuration.minSelectDate, + 'maxSelectDate': widget.configuration.maxSelectDate, 'extraDataMap': extraDataMap }); setState(() {}); @@ -139,7 +123,8 @@ class _MonthViewState extends State return ItemContainer( dateModel: dateModel, - key: ObjectKey(dateModel),//这里使用objectKey,保证可以刷新。原因1:跟flutter的刷新机制有关。原因2:statefulElement持有state。 + key: ObjectKey( + dateModel), //这里使用objectKey,保证可以刷新。原因1:跟flutter的刷新机制有关。原因2:statefulElement持有state。 ); }); } @@ -175,6 +160,13 @@ class ItemContainerState extends State { super.initState(); dateModel = widget.dateModel; isSelected = ValueNotifier(dateModel.isSelected); + + WidgetsBinding.instance.addPostFrameCallback((callback) { + if (configuration.selectMode == CalendarConstants.MODE_SINGLE_SELECT && + dateModel.isSelected) { + calendarProvider.lastClickItemState = this; + } + }); } /** @@ -220,16 +212,17 @@ class ItemContainerState extends State { calendarProvider.lastClickDateModel = dateModel; if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) { - //多选,判断是否超过限制,超过范围 - if (calendarProvider.selectedDateList.length == - configuration.maxMultiSelectCount) { - configuration.multiSelectOutOfSize(); - return; - } - if (calendarProvider.selectedDateList.contains(dateModel)) { calendarProvider.selectedDateList.remove(dateModel); } else { + //多选,判断是否超过限制,超过范围 + if (calendarProvider.selectedDateList.length == + configuration.maxMultiSelectCount) { + if (configuration.multiSelectOutOfSize != null) { + configuration.multiSelectOutOfSize(); + } + return; + } calendarProvider.selectedDateList.add(dateModel); } configuration.calendarSelect(dateModel); @@ -241,8 +234,10 @@ class ItemContainerState extends State { configuration.calendarSelect(dateModel); //单选需要刷新上一个item - calendarProvider.lastClickItemState?.refreshItem(); - calendarProvider.lastClickItemState = this; + if (calendarProvider.lastClickItemState != this) { + calendarProvider.lastClickItemState?.refreshItem(); + calendarProvider.lastClickItemState = this; + } } refreshItem(); diff --git a/lib/widget/week_view.dart b/lib/widget/week_view.dart index ddf910c..46f6944 100644 --- a/lib/widget/week_view.dart +++ b/lib/widget/week_view.dart @@ -29,29 +29,32 @@ class WeekView extends StatefulWidget { class _WeekViewState extends State { List items; - DateModel minSelectDate; - DateModel maxSelectDate; - Map extraDataMap; //自定义额外的数据 @override void initState() { super.initState(); - minSelectDate = DateModel.fromDateTime(DateTime( - widget.configuration.minSelectYear, - widget.configuration.minSelectMonth, - widget.configuration.minSelectDay)); - maxSelectDate = DateModel.fromDateTime(DateTime( - widget.configuration.maxSelectYear, - widget.configuration.maxSelectMonth, - widget.configuration.maxSelectDay)); extraDataMap = widget.configuration.extraDataMap; items = DateUtil.initCalendarForWeekView( widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0, - minSelectDate: minSelectDate, - maxSelectDate: maxSelectDate, + minSelectDate: widget.configuration.minSelectDate, + maxSelectDate: widget.configuration.maxSelectDate, extraDataMap: extraDataMap); + + //第一帧后,添加监听,generation发生变化后,需要刷新整个日历 + WidgetsBinding.instance.addPostFrameCallback((callback) { + Provider.of(context, listen: false) + .generation + .addListener(() async { + items = DateUtil.initCalendarForWeekView( + widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0, + minSelectDate: widget.configuration.minSelectDate, + maxSelectDate: widget.configuration.maxSelectDate, + extraDataMap: extraDataMap); + setState(() {}); + }); + }); } @override