From e9f98bcd9905520f6c590c3cfa9e0d9e27113ee7 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Wed, 4 Sep 2019 15:58:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=91=A8=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E6=94=AF=E6=8C=81=EF=BC=8Cweek=5Fview=5Fpager,=E5=85=88?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=B8=80=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/constants/constants.dart | 4 + lib/controller.dart | 19 +++++ lib/model/date_model.dart | 14 +++- lib/utils/date_util.dart | 26 +++++++ lib/widget/calendar_view.dart | 129 ++++++++++++++++++++++--------- lib/widget/week_view.dart | 131 ++++++++++++++++++++++++++++---- lib/widget/week_view_pager.dart | 89 ++++++++++++++++++++++ 7 files changed, 361 insertions(+), 51 deletions(-) create mode 100644 lib/widget/week_view_pager.dart diff --git a/lib/constants/constants.dart b/lib/constants/constants.dart index 62d6e67..9af2d56 100644 --- a/lib/constants/constants.dart +++ b/lib/constants/constants.dart @@ -4,6 +4,10 @@ class Constants { static const int MODE_SINGLE_SELECT = 1; static const int MODE_MULTI_SELECT = 2; + //展开状态 + static const int STATUS_EXPAND=1;//展开 + static const int STATUS_SHRINK=2;//收缩 + /** * 一周七天 */ diff --git a/lib/controller.dart b/lib/controller.dart index 7919920..68435e2 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -16,6 +16,10 @@ class CalendarController { //默认是单选,可以配置为MODE_SINGLE_SELECT,MODE_MULTI_SELECT int selectMode; + //展开状态 + bool expandStatus; + ValueNotifier expandChanged; + //日历显示的最小年份和最大年份 int minYear; int maxYear; @@ -56,10 +60,12 @@ class CalendarController { * 下面的信息不是配置的 */ List monthList = new List(); //月份list + List weekList=new List();//星期list PageController pageController; CalendarController( {int selectMode = Constants.MODE_SINGLE_SELECT, + bool expandStatus = true, DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget, WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget, int minYear = 1971, @@ -96,6 +102,8 @@ class CalendarController { this.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder; this.maxMultiSelectCount = maxMultiSelectCount; this.extraDataMap = extraDataMap; + this.expandStatus = expandStatus; + this.expandChanged=ValueNotifier(expandStatus); this.selectedDateList = Set(); if (selectedDateTimeList != null && selectedDateTimeList.isNotEmpty) { @@ -242,6 +250,17 @@ class CalendarController { } return selectDateModel; } + + //切换展开状态 + void toggleExpandStatus(){ + expandChanged.value=!expandChanged.value; + print("toggleExpandStatus:${expandChanged.value}"); + } + + void addExpandChangeListener(){ + + } + } /** diff --git a/lib/model/date_model.dart b/lib/model/date_model.dart index b6d6328..2276490 100644 --- a/lib/model/date_model.dart +++ b/lib/model/date_model.dart @@ -26,7 +26,8 @@ class DateModel { bool isInRange = false; //是否在范围内,比如可以实现在某个范围外,设置置灰的功能 bool isSelected; //是否被选中,用来实现一些标记或者选择功能 - bool isCanClick = true; //todo:是否可点击:设置范围外的日历不可点击,或者可以通过自定义拦截点击事件来设置true或者false + bool isCanClick = + true; //todo:是否可点击:设置范围外的日历不可点击,或者可以通过自定义拦截点击事件来设置true或者false @override String toString() { @@ -59,4 +60,15 @@ class DateModel { @override int get hashCode => year.hashCode ^ month.hashCode ^ day.hashCode; + + //是否是同一天 + bool isSameWith(DateModel dateModel) { + return year == dateModel.year && + month == dateModel.month && + day == dateModel.day; + } + + + + } diff --git a/lib/utils/date_util.dart b/lib/utils/date_util.dart index c139d24..429b30b 100644 --- a/lib/utils/date_util.dart +++ b/lib/utils/date_util.dart @@ -172,4 +172,30 @@ class DateUtil { print("$year年$month月:有${((preIndex + monthDayCount) / 7).toInt() + 1}行"); return ((preIndex + monthDayCount) / 7).toInt() + 1; } + + /** + * 获取本周的7个item + */ + static List initCalendarForWeekView( + int year, int month, DateTime currentDate, int weekStart, + {DateModel minSelectDate, + DateModel maxSelectDate, + Map extraDataMap}) { + List items = List(); + + int weekDay = currentDate.weekday; + + //计算本周的第一天 + DateTime firstDayOfWeek = currentDate.add(Duration(days: -weekDay)); + + for (int i = 1; i <= 7; i++) { + DateModel dateModel = + DateModel.fromDateTime(firstDayOfWeek.add(Duration(days: i))); + items.add(dateModel); + } + + print("items.toString():${items.toString()}"); + + return items; + } } diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index afbbe55..6c92d3b 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -3,7 +3,7 @@ import 'package:flutter_custom_calendar/constants/constants.dart'; import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/widget/month_view_pager.dart'; - +import 'package:flutter_custom_calendar/widget/week_view_pager.dart'; /** * 暂时默认是周一开始的 @@ -21,12 +21,27 @@ class CalendarViewWidget extends StatefulWidget { _CalendarViewWidgetState createState() => _CalendarViewWidgetState(); } -class _CalendarViewWidgetState extends State { +class _CalendarViewWidgetState extends State + with SingleTickerProviderStateMixin { double itemHeight; double totalHeight; + bool expand = true; + + AnimationController _animationController; + @override - void initState() {} + void initState() { + _animationController = + AnimationController(duration: Duration(milliseconds: 200), vsync: this); + + widget.calendarController.expandChanged.addListener(() { + print("_CalendarViewWidgetState:$expand"); + setState(() { + expand = !expand; + }); + }); + } @override Widget build(BuildContext context) { @@ -42,38 +57,82 @@ class _CalendarViewWidgetState extends State { * 利用const,避免每次setState都会刷新到这顶部的view */ widget.calendarController.weekBarItemWidgetBuilder(), - Container( - height: totalHeight, - child: MonthViewPager( - selectMode: widget.calendarController.selectMode, - monthChange: (int year, int month) { - widget.calendarController.monthChange(year, month); - }, - calendarSelect: (dateModel) { - widget.calendarController.selectDateModel =dateModel; - widget.calendarController.calendarSelect(dateModel); - }, - monthList: widget.calendarController.monthList, - pageController: widget.calendarController.pageController, - selectedDateList: widget.calendarController.selectedDateList, - selectDateModel: widget.calendarController.selectDateModel, - dayWidgetBuilder: widget.calendarController.dayWidgetBuilder, - minSelectDate: DateModel() - ..year = widget.calendarController.minSelectYear - ..month = widget.calendarController.minSelectMonth - ..day = widget.calendarController.minSelectDay, - maxSelectDate: DateModel() - ..year = widget.calendarController.maxSelectYear - ..month = widget.calendarController.maxSelectMonth - ..day = widget.calendarController.maxSelectDay, - maxMultiSelectCount: - widget.calendarController.maxMultiSelectCount, - multiSelectOutOfRange: - widget.calendarController.multiSelectOutOfRange, - multiSelectOutOfSize: - widget.calendarController.multiSelectOutOfSize, - extraDataMap: widget.calendarController.extraDataMap, - ), + AnimatedContainer( + duration: Duration(milliseconds: 500), + height: expand ? totalHeight : itemHeight, + child: expand + ? Container( + height: totalHeight, + child: MonthViewPager( + selectMode: widget.calendarController.selectMode, + monthChange: (int year, int month) { + widget.calendarController.monthChange(year, month); + }, + calendarSelect: (dateModel) { + widget.calendarController.selectDateModel = dateModel; + widget.calendarController.calendarSelect(dateModel); + }, + monthList: widget.calendarController.monthList, + pageController: widget.calendarController.pageController, + selectedDateList: + widget.calendarController.selectedDateList, + selectDateModel: + widget.calendarController.selectDateModel, + dayWidgetBuilder: + widget.calendarController.dayWidgetBuilder, + minSelectDate: DateModel() + ..year = widget.calendarController.minSelectYear + ..month = widget.calendarController.minSelectMonth + ..day = widget.calendarController.minSelectDay, + maxSelectDate: DateModel() + ..year = widget.calendarController.maxSelectYear + ..month = widget.calendarController.maxSelectMonth + ..day = widget.calendarController.maxSelectDay, + maxMultiSelectCount: + widget.calendarController.maxMultiSelectCount, + multiSelectOutOfRange: + widget.calendarController.multiSelectOutOfRange, + multiSelectOutOfSize: + widget.calendarController.multiSelectOutOfSize, + extraDataMap: widget.calendarController.extraDataMap, + ), + ) + : Container( + height: itemHeight, + child: WeekViewPager( + selectMode: widget.calendarController.selectMode, + monthChange: (int year, int month) { + widget.calendarController.monthChange(year, month); + }, + calendarSelect: (dateModel) { + widget.calendarController.selectDateModel = dateModel; + widget.calendarController.calendarSelect(dateModel); + }, + weekList: widget.calendarController.weekList, + pageController: widget.calendarController.pageController, + selectedDateList: + widget.calendarController.selectedDateList, + selectDateModel: + widget.calendarController.selectDateModel, + dayWidgetBuilder: + widget.calendarController.dayWidgetBuilder, + minSelectDate: DateModel() + ..year = widget.calendarController.minSelectYear + ..month = widget.calendarController.minSelectMonth + ..day = widget.calendarController.minSelectDay, + maxSelectDate: DateModel() + ..year = widget.calendarController.maxSelectYear + ..month = widget.calendarController.maxSelectMonth + ..day = widget.calendarController.maxSelectDay, + maxMultiSelectCount: + widget.calendarController.maxMultiSelectCount, + multiSelectOutOfRange: + widget.calendarController.multiSelectOutOfRange, + multiSelectOutOfSize: + widget.calendarController.multiSelectOutOfSize, + extraDataMap: widget.calendarController.extraDataMap, + ), + ), ), ], ), diff --git a/lib/widget/week_view.dart b/lib/widget/week_view.dart index 3ce0cf8..f887016 100644 --- a/lib/widget/week_view.dart +++ b/lib/widget/week_view.dart @@ -1,31 +1,132 @@ import 'package:flutter/material.dart'; +import 'package:flutter_custom_calendar/constants/constants.dart'; +import 'package:flutter_custom_calendar/controller.dart'; +import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart'; /** * 周视图,只显示本周的日子 */ class WeekView extends StatefulWidget { + OnCalendarSelect onCalendarSelectListener; + + Set selectedDateList; //被选中的日期 + + DateModel selectDateModel; //当前选择项,用于单选 + + DayWidgetBuilder dayWidgetBuilder; + + OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围 + OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数 + + int year; + int month; + int day; + + DateModel minSelectDate; + DateModel maxSelectDate; + + int selectMode; + int maxMultiSelectCount; + + Map extraDataMap; //自定义额外的数据 + + WeekView( + {@required this.year, + @required this.month, + this.day, + this.onCalendarSelectListener, + this.dayWidgetBuilder, + this.selectedDateList, + this.selectDateModel, + this.minSelectDate, + this.maxSelectDate, + this.selectMode, + this.multiSelectOutOfSize, + this.multiSelectOutOfRange, + this.maxMultiSelectCount, + this.extraDataMap}); + @override _WeekViewState createState() => _WeekViewState(); } class _WeekViewState extends State { + List items; + DateModel selectDateModel; //当前选择项,用于单选 + + @override + void initState() { + super.initState(); + items=DateUtil.initCalendarForWeekView(2019, 9, DateTime.now(), 0); + + } + @override Widget build(BuildContext context) { -// DateTime dateTime = DateTime.now(); -// -// print(dateTime); -// -// print(dateTime.subtract(Duration(days: 1))); -// -// var berlinWallFell = new DateTime(1989, DateTime.november, 9); -// var dDay = new DateTime(1944, DateTime.june, 6); -// Duration difference = berlinWallFell.difference(dDay); -// print(difference.inDays); - - print(DateUtil.initCalendarForMonthView( - 2019, 12, DateTime.now(), DateTime.sunday)); - - return Container(); + + + return new GridView.builder( + physics: NeverScrollableScrollPhysics(), + gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, mainAxisSpacing: 10), + itemCount: 7, + itemBuilder: (context, index) { + DateModel dateModel = items[index]; + //判断是否被选择 + if (widget.selectMode == Constants.MODE_MULTI_SELECT) { + if (widget.selectedDateList.contains(dateModel)) { + dateModel.isSelected = true; + } else { + dateModel.isSelected = false; + } + } else { + if (selectDateModel == dateModel) { + dateModel.isSelected = true; + } else { + dateModel.isSelected = false; + } + } + + return GestureDetector( + onTap: () { + //范围外不可点击 + if (!dateModel.isInRange) { + //多选回调 + if (widget.selectMode == Constants.MODE_MULTI_SELECT) { + widget.multiSelectOutOfRange(); + } + return; + } + + if (widget.selectMode == Constants.MODE_MULTI_SELECT) { + //多选,判断是否超过限制,超过范围 + if (widget.selectedDateList.length == + widget.maxMultiSelectCount) { + widget.multiSelectOutOfSize(); + return; + } + + //多选也可以弄这些单选的代码 + selectDateModel = dateModel; + widget.selectDateModel = dateModel; + widget.onCalendarSelectListener(dateModel); + setState(() { + if (widget.selectedDateList.contains(dateModel)) { + widget.selectedDateList.remove(dateModel); + } else { + widget.selectedDateList.add(dateModel); + } + }); + } else { + selectDateModel = dateModel; + widget.selectDateModel = dateModel; + widget.onCalendarSelectListener(dateModel); + setState(() {}); + } + }, + child: widget.dayWidgetBuilder(dateModel), + ); + }); } } diff --git a/lib/widget/week_view_pager.dart b/lib/widget/week_view_pager.dart new file mode 100644 index 0000000..0274719 --- /dev/null +++ b/lib/widget/week_view_pager.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_calendar/controller.dart'; +import 'package:flutter_custom_calendar/model/date_model.dart'; +import 'package:flutter_custom_calendar/widget/week_view.dart'; + +class WeekViewPager extends StatefulWidget { + final OnMonthChange monthChange; + + final OnCalendarSelect calendarSelect; + final DayWidgetBuilder dayWidgetBuilder; + OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围 + OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数 + + Set selectedDateList; //被选中的日期,用于多选 + DateModel selectDateModel; //当前选择项,用于单选 + + final List weekList; + PageController pageController; + + DateModel minSelectDate; + DateModel maxSelectDate; + + int selectMode; + int maxMultiSelectCount; + + Map extraDataMap; //自定义额外的数据 + + WeekViewPager( + {this.monthChange, + this.calendarSelect, + this.weekList, + this.pageController, + this.selectedDateList, + this.selectDateModel, + this.dayWidgetBuilder, + this.minSelectDate, + this.maxSelectDate, + this.selectMode, + this.maxMultiSelectCount, + this.multiSelectOutOfRange, + this.multiSelectOutOfSize, + this.extraDataMap}); + + @override + _WeekViewPagerState createState() => _WeekViewPagerState(); +} + +class _WeekViewPagerState extends State { + + int lastMonth;//上一个月份 + + @override + void initState() { +// lastMonth= + } + + @override + Widget build(BuildContext context) { + return Container( + child: PageView.builder( + onPageChanged: (position) { + //月份的变化 + DateModel dateModel = widget.weekList[position]; + widget.monthChange(dateModel.year, dateModel.month); + }, + controller: widget.pageController, + itemBuilder: (context, index) { + DateModel dateModel = widget.weekList[index]; + return new WeekView( + selectMode: widget.selectMode, + year: dateModel.year, + month: dateModel.month, + selectDateModel: widget.selectDateModel, + selectedDateList: widget.selectedDateList, + onCalendarSelectListener: widget.calendarSelect, + dayWidgetBuilder: widget.dayWidgetBuilder, + minSelectDate: widget.minSelectDate, + maxSelectDate: widget.maxSelectDate, + maxMultiSelectCount: widget.maxMultiSelectCount, + multiSelectOutOfRange: widget.multiSelectOutOfRange, + multiSelectOutOfSize: widget.multiSelectOutOfSize, + extraDataMap: widget.extraDataMap, + ); + }, + itemCount: widget.weekList.length, + ), + ); + } +}