From ed78d3f753c3c8607535a1d03d21bbd8b61bbdf5 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Thu, 10 Oct 2019 09:33:40 +0800 Subject: [PATCH 01/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 175c43a..e0987c4 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,21 @@ -FlutterCalendarWidget + +## FlutterCalendarWidget Flutter上的一个日历控件,可以定制成自己想要的样子。 - - +## 介绍 +之前写了一个Flutter日历的开源库,最近增加了一些功能,并且对代码进行了一下重构。(之前的代码写得真的是****,没搞状态框架,还各种嵌套代码) + +## 示例 + + + + + + + + + ## 主要功能 @@ -57,9 +69,9 @@ CalendarViewWidget({@required this.calendarController, this.boxDecoration}); ## 配置CalendarController -下面是CalendarController中一些支持自定义配置的属性。不配置的话,会有对应的默认值。 +下面是CalendarController中一些支持自定义配置的属性。不配置的话,会有对应的默认值。(配置现在都是在controller这里进行配置的,内部会将配置的数据抽成Configuration类) -个人觉得,配置的含义主要包括了3个方面的配置。 +配置的含义主要包括了3个方面的配置。 * 一个是显示日历所需要的相关数据, * 一个是显示日历的自定义UI的相关配置, * 一个是对日历的监听事件进行配置。 @@ -307,12 +319,4 @@ extraData|自定义的额外数据|Object|默认为空 :-: | :-: | DateTime getDateTime()|将DateModel转化成DateTime DateModel fromDateTime(DateTime dateTime)|根据DateTime创建对应的model,并初始化农历和传统节日等信息 -bool operator ==(Object other)|重写==方法,可以判断两个dateModel是否是同一天 - - - -## TODO LIST -* 优化代码实现 -* 继续写几个不同风格的Demo -* 支持手势操作 -* 实现高度自适应 +bool operator ==(Object other)|重写==方法,可以判断两个dateModel是否是同一天 \ No newline at end of file From 049fa79025714cfc9805df9f4f86788b6c3f45e4 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Thu, 10 Oct 2019 09:36:06 +0800 Subject: [PATCH 02/25] =?UTF-8?q?=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e0987c4..e62c030 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 之前写了一个Flutter日历的开源库,最近增加了一些功能,并且对代码进行了一下重构。(之前的代码写得真的是****,没搞状态框架,还各种嵌套代码) ## 示例 + +日历支持web预览:[点击此处进入预览](https://lxd312569496.github.io/flutter_custom_calendar/#/) + From ea83dc2739f1d2418d43947322ba1b89c787832d Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Mon, 14 Oct 2019 20:16:53 +0800 Subject: [PATCH 03/25] =?UTF-8?q?=E5=85=B3=E9=97=AD=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E7=9A=84=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/utils/LogUtil.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/LogUtil.dart b/lib/utils/LogUtil.dart index 73feb87..3bab744 100644 --- a/lib/utils/LogUtil.dart +++ b/lib/utils/LogUtil.dart @@ -4,7 +4,7 @@ import 'package:flutter/cupertino.dart'; * 打印日志,外部可以控制日历信息的打印显示,方便调试查错 */ class LogUtil { - static bool _enableLog = true; //是否可以打印日志 + static bool _enableLog = false; //是否可以打印日志 static set enableLog(bool value) { _enableLog = value; From 8b45252b9f4af08e320d227f77163c7b0a882253 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 15 Oct 2019 22:01:29 +0800 Subject: [PATCH 04/25] =?UTF-8?q?=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/model/date_model.dart | 11 +++ lib/widget/month_view.dart | 112 ++++++++++++++++++------------- lib/widget/month_view_pager.dart | 7 +- lib/widget/week_view_pager.dart | 6 +- 4 files changed, 88 insertions(+), 48 deletions(-) diff --git a/lib/model/date_model.dart b/lib/model/date_model.dart index 4061ea2..0882e3b 100644 --- a/lib/model/date_model.dart +++ b/lib/model/date_model.dart @@ -124,3 +124,14 @@ class DateModel { return this.getDateTime().isBefore(dateModel.getDateTime()); } } + +class X { + var _y; + + get y => null == _y ? initY() : _y; + + initY() { + //do some computation + _y = "result"; + } +} diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 1d0c85c..27d783b 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -22,11 +22,12 @@ class MonthView extends StatefulWidget { final CalendarConfiguration configuration; const MonthView({ + Key key, @required this.year, @required this.month, this.day, this.configuration, - }); + }) : super(key: key); @override _MonthViewState createState() => _MonthViewState(); @@ -34,13 +35,13 @@ class MonthView extends StatefulWidget { class _MonthViewState extends State with AutomaticKeepAliveClientMixin { - List items; + List items = List(); int lineCount; - double itemHeight; - double totalHeight; - double mainSpacing = 10; +// double itemHeight; +// double totalHeight; +// double mainSpacing = 10; DateModel minSelectDate; DateModel maxSelectDate; @@ -68,38 +69,48 @@ class _MonthViewState extends State items = CacheData.getInstance().monthListCache[firstDayOfMonth]; } else { LogUtil.log(TAG: this.runtimeType, message: "缓存中无数据"); - items = DateUtil.initCalendarForMonthView( - widget.year, widget.month, DateTime.now(), DateTime.sunday, - minSelectDate: minSelectDate, - maxSelectDate: maxSelectDate, - extraDataMap: extraDataMap); + getItems(); CacheData.getInstance().monthListCache[firstDayOfMonth] = items; } lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); } + getItems() async { + items = await compute(initCalendarForMonthView, { + 'year': widget.year, + 'month': widget.month, + 'minSelectDate': minSelectDate, + 'maxSelectDate': maxSelectDate, + 'extraDataMap': extraDataMap + }); + setState(() {}); + } + + static Future> initCalendarForMonthView(Map map) async { + return DateUtil.initCalendarForMonthView( + map['year'], map['month'], DateTime.now(), DateTime.sunday, + minSelectDate: map['minSelectDate'], + maxSelectDate: map['maxSelectDate'], + extraDataMap: map['extraDataMap']); + } + @override Widget build(BuildContext context) { super.build(context); LogUtil.log(TAG: this.runtimeType, message: "_MonthViewState build"); - itemHeight = MediaQuery.of(context).size.width / 7; - totalHeight = itemHeight * lineCount + mainSpacing * (lineCount - 1); - return Container(height: totalHeight, child: getView()); - } - - Widget getView() { CalendarProvider calendarProvider = Provider.of(context, listen: false); CalendarConfiguration configuration = calendarProvider.calendarConfiguration; return new GridView.builder( - physics: NeverScrollableScrollPhysics(), - gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( + addAutomaticKeepAlives: true, + physics: const NeverScrollableScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, mainAxisSpacing: 10), - itemCount: 7 * lineCount, + itemCount: items.isEmpty ? 0 : 7 * lineCount, itemBuilder: (context, index) { DateModel dateModel = items[index]; //判断是否被选择 @@ -119,8 +130,6 @@ class _MonthViewState extends State return ItemContainer( dateModel: dateModel, -// configuration: configuration, -// calendarProvider: calendarProvider, ); }); } @@ -135,9 +144,6 @@ class _MonthViewState extends State class ItemContainer extends StatefulWidget { final DateModel dateModel; -// CalendarConfiguration configuration; -// CalendarProvider calendarProvider; - const ItemContainer({ Key key, this.dateModel, @@ -161,9 +167,26 @@ class ItemContainerState extends State { isSelected = ValueNotifier(dateModel.isSelected); } + /** + * 提供方法给外部,可以调用这个方法进行刷新item + */ + void refreshItem() { + /** + Exception caught by gesture + The following assertion was thrown while handling a gesture: + setState() called after dispose() + */ + if (mounted) { + setState(() { + dateModel.isSelected = !dateModel.isSelected; +// isSelected.value = !isSelected.value; + }); + } + } + @override Widget build(BuildContext context) { -// LogUtil.log(TAG: this.runtimeType,message: "ItemContainerState build"); + LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState build"); calendarProvider = Provider.of(context, listen: false); configuration = calendarProvider.calendarConfiguration; @@ -215,29 +238,26 @@ class ItemContainerState extends State { refreshItem(); }, child: configuration.dayWidgetBuilder(dateModel), -// child: ValueListenableBuilder( -// valueListenable: isSelected, -// builder: (BuildContext context, bool value, Widget child) { -// return configuration.dayWidgetBuilder(dateModel); -// }), ); } - /** - * 刷新item - */ - void refreshItem() { - /** - * - Exception caught by gesture - The following assertion was thrown while handling a gesture: - setState() called after dispose() - */ - if (mounted) { - setState(() { - dateModel.isSelected = !dateModel.isSelected; -// isSelected.value = !isSelected.value; - }); - } + @override + void deactivate() { + LogUtil.log( + TAG: this.runtimeType, message: "ItemContainerState deactivate"); + super.deactivate(); + } + + @override + void dispose() { + LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState dispose"); + super.dispose(); + } + + @override + void didUpdateWidget(ItemContainer oldWidget) { + LogUtil.log( + TAG: this.runtimeType, message: "ItemContainerState didUpdateWidget"); + super.didUpdateWidget(oldWidget); } } diff --git a/lib/widget/month_view_pager.dart b/lib/widget/month_view_pager.dart index 4e140bd..1925717 100644 --- a/lib/widget/month_view_pager.dart +++ b/lib/widget/month_view_pager.dart @@ -15,7 +15,7 @@ class MonthViewPager extends StatefulWidget { _MonthViewPagerState createState() => _MonthViewPagerState(); } -class _MonthViewPagerState extends State { +class _MonthViewPagerState extends State with AutomaticKeepAliveClientMixin{ CalendarProvider calendarProvider; @override @@ -57,6 +57,8 @@ class _MonthViewPagerState extends State { @override Widget build(BuildContext context) { + super.build(context); + LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager build"); // 获取到当前的CalendarProvider对象,设置listen为false,不需要刷新 calendarProvider = Provider.of(context, listen: false); CalendarConfiguration configuration = @@ -110,4 +112,7 @@ class _MonthViewPagerState extends State { itemCount: configuration.monthList.length, ); } + + @override + bool get wantKeepAlive => true; } diff --git a/lib/widget/week_view_pager.dart b/lib/widget/week_view_pager.dart index 5858098..0ba52e8 100644 --- a/lib/widget/week_view_pager.dart +++ b/lib/widget/week_view_pager.dart @@ -14,7 +14,7 @@ class WeekViewPager extends StatefulWidget { _WeekViewPagerState createState() => _WeekViewPagerState(); } -class _WeekViewPagerState extends State { +class _WeekViewPagerState extends State with AutomaticKeepAliveClientMixin{ int lastMonth; //保存上一个月份,不然不知道月份发生了变化 CalendarProvider calendarProvider; @@ -37,6 +37,7 @@ class _WeekViewPagerState extends State { @override Widget build(BuildContext context) { + super.build(context); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager build"); // 获取到当前的CalendarProvider对象,设置listen为false,不需要刷新 @@ -92,4 +93,7 @@ class _WeekViewPagerState extends State { ), ); } + + @override + bool get wantKeepAlive => true; } From 083abc01ca00e497b74785a20374012a5fa059ae Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 29 Oct 2019 17:46:49 +0800 Subject: [PATCH 05/25] =?UTF-8?q?=E6=94=AF=E6=8C=81verticalSpacing?= =?UTF-8?q?=E5=92=8CitemSize=E5=B1=9E=E6=80=A7=EF=BC=8C=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/widget/calendar_view.dart | 23 +++++++++++------------ lib/widget/month_view.dart | 4 ++-- lib/widget/month_view_pager.dart | 24 ++++++++++++------------ 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index b3e7a36..4d22306 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -151,14 +151,17 @@ class CalendarContainerState extends State MediaQueryData mediaQueryData = MediaQueryData.fromWindow(WidgetsBinding.instance.window); - itemHeight = calendarProvider.calendarConfiguration.itemSize ?? - mediaQueryData.orientation == Orientation.landscape - ? mediaQueryData.size.height / 10 - : mediaQueryData.size.width / 7; - if (calendarProvider.totalHeight == null) { - calendarProvider.totalHeight = itemHeight * 6 + - calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1); - } + print("mediaQueryData.orientation:${mediaQueryData}"); + //如果itemSize为空,默认是宽度/7。网页版的话是高度/7 + itemHeight = calendarProvider.calendarConfiguration.itemSize != null + ? calendarProvider.calendarConfiguration.itemSize + : mediaQueryData.orientation == Orientation.landscape + ? mediaQueryData.size.height / 7 + : mediaQueryData.size.width / 7; + + calendarProvider.totalHeight = itemHeight * 6 + + calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1); + totalHeight = calendarProvider.totalHeight; } @override @@ -172,10 +175,6 @@ class CalendarContainerState extends State //暂时先这样写死,提前计算布局的高度,不然会出现问题:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand. // itemHeight = calendarProvider.calendarConfiguration.itemSize ?? // MediaQuery.of(context).size.width / 7; - if (totalHeight == null) { - totalHeight = itemHeight * 6 + - calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1); - } return Container( width: itemHeight * 7, child: new Column( diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 27d783b..6ee8fee 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -108,8 +108,8 @@ class _MonthViewState extends State return new GridView.builder( addAutomaticKeepAlives: true, physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 7, mainAxisSpacing: 10), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 7, mainAxisSpacing: configuration.verticalSpacing), itemCount: items.isEmpty ? 0 : 7 * lineCount, itemBuilder: (context, index) { DateModel dateModel = items[index]; diff --git a/lib/widget/month_view_pager.dart b/lib/widget/month_view_pager.dart index 1925717..9fceaab 100644 --- a/lib/widget/month_view_pager.dart +++ b/lib/widget/month_view_pager.dart @@ -86,18 +86,18 @@ class _MonthViewPagerState extends State with AutomaticKeepAlive if (calendarProvider.calendarConfiguration.showMode != Constants.MODE_SHOW_ONLY_WEEK) { //月份切换的时候,如果高度发生变化的话,需要setState使高度整体自适应 - int lineCount = - DateUtil.getMonthViewLineCount(dateModel.year, dateModel.month); - double newHeight = (calendarProvider.calendarConfiguration.itemSize ?? - MediaQuery.of(context).size.width / 7) * - lineCount + - calendarProvider.calendarConfiguration.verticalSpacing * - (lineCount - 1); - if (calendarProvider.totalHeight.toInt() != newHeight.toInt()) { - LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); - calendarProvider.totalHeight = newHeight; -// calendarProvider.changeTotalHeight(newHeight); - } +// int lineCount = +// DateUtil.getMonthViewLineCount(dateModel.year, dateModel.month); +// double newHeight = (calendarProvider.calendarConfiguration.itemSize ?? +// MediaQuery.of(context).size.width / 7) * +// lineCount + +// calendarProvider.calendarConfiguration.verticalSpacing * +// (lineCount - 1); +// if (calendarProvider.totalHeight.toInt() != newHeight.toInt()) { +// LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); +// calendarProvider.totalHeight = newHeight; +//// calendarProvider.changeTotalHeight(newHeight); +// } } }, controller: configuration.monthController, From 389ce46a29b1a3df37da9848763cf12106adfb3d Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 29 Oct 2019 19:32:42 +0800 Subject: [PATCH 06/25] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E6=9C=88=E8=A7=86=E5=9B=BE=E5=92=8C=E5=91=A8=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5=EF=BC=8C=E4=BC=98=E5=85=88=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E5=91=A8=E8=A7=86=E5=9B=BE=EF=BC=8CMODE=5FSHOW=5FWEEK?= =?UTF-8?q?=5FAND=5FMONTH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/calendar_provider.dart | 3 ++- lib/constants/constants.dart | 3 ++- lib/controller.dart | 12 ++++++------ lib/widget/calendar_view.dart | 24 ++++++++++++++++-------- lib/widget/month_view.dart | 12 ++++++------ 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/lib/calendar_provider.dart b/lib/calendar_provider.dart index b98daab..888ec43 100644 --- a/lib/calendar_provider.dart +++ b/lib/calendar_provider.dart @@ -110,7 +110,8 @@ class CalendarProvider extends ChangeNotifier { ? selectDateModel : DateModel.fromDateTime(DateTime.now()) ..day = 15; - if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK) { + if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK || + calendarConfiguration.showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) { expandStatus = ValueNotifier(false); } else { expandStatus = ValueNotifier(true); diff --git a/lib/constants/constants.dart b/lib/constants/constants.dart index 4042090..c87b3ac 100644 --- a/lib/constants/constants.dart +++ b/lib/constants/constants.dart @@ -7,7 +7,8 @@ class Constants { //展示模式 static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图 static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图 - static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持月和星期视图切换 + static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图 + static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 /** diff --git a/lib/controller.dart b/lib/controller.dart index 386aa86..27bec8c 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -93,8 +93,7 @@ class CalendarController { maxYearMonth, ))}"); - if (showMode == Constants.MODE_SHOW_ONLY_MONTH || - showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) { + if (showMode != Constants.MODE_SHOW_ONLY_WEEK) { //初始化pageController,initialPage默认是当前时间对于的页面 int initialPage = 0; int nowMonthIndex = 0; @@ -132,8 +131,7 @@ class CalendarController { "初始化月份视图的信息:一共有${monthList.length}个月,initialPage为${nowMonthIndex}"); } - if (showMode == Constants.MODE_SHOW_ONLY_WEEK || - showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) { + if (showMode != Constants.MODE_SHOW_ONLY_MONTH) { //计算一共多少周 //计算方法:第一天是周几,最后一天是周几,中间的天数/7后加上2就是结果了 int initialWeekPage = 0; @@ -230,7 +228,8 @@ class CalendarController { calendarProvider.calendarConfiguration.monthController .previousPage(duration: DEFAULT_DURATION, curve: Curves.ease); calendarProvider.calendarConfiguration.monthChange( - monthList[currentIndex-1].year, monthList[currentIndex-1].month); + monthList[currentIndex - 1].year, + monthList[currentIndex - 1].month); DateModel temp = new DateModel(); temp.year = monthList[currentIndex].year; temp.month = monthList[currentIndex].month; @@ -268,7 +267,8 @@ class CalendarController { calendarProvider.calendarConfiguration.monthController .nextPage(duration: DEFAULT_DURATION, curve: Curves.ease); calendarProvider.calendarConfiguration.monthChange( - monthList[currentIndex+1].year, monthList[currentIndex+1].month); + monthList[currentIndex + 1].year, + monthList[currentIndex + 1].month); DateModel temp = new DateModel(); temp.year = monthList[currentIndex].year; temp.month = monthList[currentIndex].month; diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index 4d22306..b403203 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -73,12 +73,10 @@ class CalendarContainerState extends State double itemHeight; double totalHeight; - bool expand = true; + bool expand; CalendarProvider calendarProvider; - var state = CrossFadeState.showFirst; - List widgets = []; int index = 0; @@ -95,20 +93,28 @@ class CalendarContainerState extends State Constants.MODE_SHOW_WEEK_AND_MONTH) { widgets.add(const MonthViewPager()); widgets.add(const WeekViewPager()); + index = 1; + } else if (calendarProvider.calendarConfiguration.showMode == + Constants.MODE_SHOW_MONTH_AND_WEEK) { + widgets.add(const MonthViewPager()); + widgets.add(const WeekViewPager()); + index = 0; } else { //默认是只显示月视图 widgets.add(const MonthViewPager()); } + expand = calendarProvider.expandStatus.value; //如果需要视图切换的话,才需要添加监听,不然不需要监听变化 if (calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_WEEK_AND_MONTH) { + Constants.MODE_SHOW_WEEK_AND_MONTH || + calendarProvider.calendarConfiguration.showMode == + Constants.MODE_SHOW_MONTH_AND_WEEK) { calendarProvider.expandStatus.addListener(() { setState(() { + print( + "calendarProvider.expandStatus.value:${calendarProvider.expandStatus.value}"); expand = calendarProvider.expandStatus.value; - state = (state == CrossFadeState.showSecond - ? CrossFadeState.showFirst - : CrossFadeState.showSecond); if (expand) { index = 0; //周视图切换到月视图 @@ -122,6 +128,9 @@ class CalendarContainerState extends State } }); }); + }else{ + index=0; + } // widget.calendarController.addMonthChangeListener((year, month) { @@ -151,7 +160,6 @@ class CalendarContainerState extends State MediaQueryData mediaQueryData = MediaQueryData.fromWindow(WidgetsBinding.instance.window); - print("mediaQueryData.orientation:${mediaQueryData}"); //如果itemSize为空,默认是宽度/7。网页版的话是高度/7 itemHeight = calendarProvider.calendarConfiguration.itemSize != null ? calendarProvider.calendarConfiguration.itemSize diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 6ee8fee..010dcf0 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -186,7 +186,7 @@ class ItemContainerState extends State { @override Widget build(BuildContext context) { - LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState build"); +// LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState build"); calendarProvider = Provider.of(context, listen: false); configuration = calendarProvider.calendarConfiguration; @@ -243,21 +243,21 @@ class ItemContainerState extends State { @override void deactivate() { - LogUtil.log( - TAG: this.runtimeType, message: "ItemContainerState deactivate"); +// LogUtil.log( +// TAG: this.runtimeType, message: "ItemContainerState deactivate"); super.deactivate(); } @override void dispose() { - LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState dispose"); +// LogUtil.log(TAG: this.runtimeType, message: "ItemContainerState dispose"); super.dispose(); } @override void didUpdateWidget(ItemContainer oldWidget) { - LogUtil.log( - TAG: this.runtimeType, message: "ItemContainerState didUpdateWidget"); +// LogUtil.log( +// TAG: this.runtimeType, message: "ItemContainerState didUpdateWidget"); super.didUpdateWidget(oldWidget); } } From dafc20dd39811fa64b91bc3fe6a3554b2b43f655 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 29 Oct 2019 20:38:11 +0800 Subject: [PATCH 07/25] =?UTF-8?q?controller=E6=8F=90=E4=BE=9BchangeExtraDa?= =?UTF-8?q?taMap=E6=96=B9=E6=B3=95=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E4=BF=AE=E6=94=B9=E8=87=AA=E5=AE=9A=E4=B9=89=E6=95=B0?= =?UTF-8?q?=E6=8D=AEextraDataMap=E3=80=82=20=E6=9C=89=E5=9D=91=EF=BC=8C?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E7=94=A8=E5=88=B0ObjectKey=EF=BC=8C=E8=B7=9F?= =?UTF-8?q?Flutter=E7=9A=84=E5=88=B7=E6=96=B0=E6=9C=BA=E5=88=B6=E6=9C=89?= =?UTF-8?q?=E5=85=B3=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/controller.dart | 6 ++++++ lib/utils/date_util.dart | 4 ++++ lib/widget/month_view.dart | 11 +++++++++++ 3 files changed, 21 insertions(+) diff --git a/lib/controller.dart b/lib/controller.dart index 27bec8c..d61432b 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -214,6 +214,12 @@ class CalendarController { }); } + //可以动态修改extraDataMap + void changeExtraData(Map newMap) { + this.calendarConfiguration.extraDataMap = newMap; + this.calendarProvider.generation.value++; + } + /** * 月份或者星期的上一页 */ diff --git a/lib/utils/date_util.dart b/lib/utils/date_util.dart index 856feee..6f63d71 100644 --- a/lib/utils/date_util.dart +++ b/lib/utils/date_util.dart @@ -168,7 +168,11 @@ class DateUtil { if (extraDataMap?.isNotEmpty == true) { if (extraDataMap.containsKey(dateModel)) { dateModel.extraData = extraDataMap[dateModel]; + }else{ + dateModel.extraData=null; } + }else{ + dateModel.extraData=null; } result.add(dateModel); diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 010dcf0..019ea69 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -74,6 +74,16 @@ class _MonthViewState extends State } lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); + + //第一帧后 + WidgetsBinding.instance.addPostFrameCallback((callback) { + Provider.of(context, listen: false) + .generation + .addListener(() async { + extraDataMap={}; + await getItems(); + }); + }); } getItems() async { @@ -130,6 +140,7 @@ class _MonthViewState extends State return ItemContainer( dateModel: dateModel, + key: ObjectKey(dateModel),//这里使用objectKey,保证可以刷新。原因1:跟flutter的刷新机制有关。原因2:statefulElement持有state。 ); }); } From cac3b44b33b2310def92e761fe2f3df450f74d27 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 14:04:44 +0800 Subject: [PATCH 08/25] =?UTF-8?q?=E6=97=A5=E5=8E=86=E5=A2=9E=E5=8A=A0paddi?= =?UTF-8?q?ng=E5=92=8Cmargin=E5=B1=9E=E6=80=A7=20=E6=97=A5=E5=8E=86?= =?UTF-8?q?=E9=AB=98=E5=BA=A6=E8=87=AA=E9=80=82=E5=BA=94=20=E6=97=A5?= =?UTF-8?q?=E5=8E=86item=E5=A4=A7=E5=B0=8F=E8=AE=A1=E7=AE=97=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/blue_style_page.dart | 253 ++++++++++++++++++++++++++++ example/lib/custom_sign_page.dart | 1 + example/lib/default_style_page.dart | 6 +- example/lib/main.dart | 69 ++++++++ lib/calendar_provider.dart | 54 +++++- lib/configuration.dart | 13 +- lib/controller.dart | 31 +++- lib/widget/calendar_view.dart | 82 +++++---- lib/widget/month_view.dart | 1 + lib/widget/month_view_pager.dart | 25 +-- lib/widget/week_view_pager.dart | 8 +- 11 files changed, 458 insertions(+), 85 deletions(-) create mode 100644 example/lib/blue_style_page.dart diff --git a/example/lib/blue_style_page.dart b/example/lib/blue_style_page.dart new file mode 100644 index 0000000..ab4a71f --- /dev/null +++ b/example/lib/blue_style_page.dart @@ -0,0 +1,253 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; +import 'package:flutter_custom_calendar/style/style.dart'; +import 'package:random_pk/random_pk.dart'; + +/** + * 自定义一些额外的数据,实现标记功能 + */ +class BlueStylePage extends StatefulWidget { + BlueStylePage({Key key, this.title}) : super(key: key); + + final String title; + + @override + _BlueStylePageState createState() => _BlueStylePageState(); +} + +class _BlueStylePageState extends State { + ValueNotifier text; + ValueNotifier selectText; + + CalendarController controller; + + Map customExtraData = {}; + + @override + void initState() { + controller = new CalendarController( + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }, + showMode: Constants.MODE_SHOW_MONTH_AND_WEEK, + extraDataMap: customExtraData); + + controller.addMonthChangeListener( + (year, month) { + text.value = "$year年$month月"; + }, + ); + + controller.addOnCalendarSelectListener((dateModel) { + //刷新选择的时间 + selectText.value = + "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"; + }); + + text = new ValueNotifier("${DateTime.now().year}年${DateTime.now().month}月"); + + selectText = new ValueNotifier( + "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); + } + + @override + Widget build(BuildContext context) { + var calendarWidget = CalendarViewWidget( + calendarController: controller, + boxDecoration: BoxDecoration( + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)), + color: Colors.white, + ), + padding: EdgeInsets.only(left: 20, right: 20, bottom: 10), + margin: const EdgeInsets.only( + left: 15, + right: 15, + ), + ); + + return SafeArea( + child: Scaffold( + appBar: AppBar( + backgroundColor: Color(0xff6219EC), + ), + backgroundColor: Color(0xff6219EC), + body: new Container( + child: new Column( + children: [ + SizedBox( + height: 20, + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 100, + margin: const EdgeInsets.only(left: 15, right: 15), + decoration: BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), + color: Colors.white), + child: Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 30), + child: RichText( + text: TextSpan( + children: [ + TextSpan( + text: "Februaly", + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.w700, + fontSize: 30), + ), + TextSpan( + text: " 2019", + style: TextStyle( + color: Colors.black, fontSize: 30), + ), + ], + ), + ), + ), + ], + ), + ), + calendarWidget + ], + ), + ValueListenableBuilder( + valueListenable: selectText, + builder: (context, value, child) { + return new Text(selectText.value); + }), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + controller.toggleExpandStatus(); + }, + tooltip: 'Increment', + child: Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ), + ); + } +} + +class CustomStyleWeekBarItem extends BaseWeekBar { + List weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"]; + + //可以直接重写build方法 + @override + Widget build(BuildContext context) { + List children = List(); + + var items = getWeekDayWidget(); + children.add(Row( + children: items, + )); + children.add(Divider( + color: Colors.grey, + )); + return Column( + children: children, + ); + } + + @override + Widget getWeekBarItem(int index) { + return new Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: new Center( + child: new Text( + weekList[index], + style: + TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)), + ), + ), + ); + } +} + +class CustomStyleDayWidget extends BaseCombineDayWidget { + CustomStyleDayWidget(DateModel dateModel) : super(dateModel); + + TextStyle normalTextStyle = + TextStyle(fontWeight: FontWeight.w700, color: Colors.black); + + TextStyle noIsCurrentMonthTextStyle = + TextStyle(fontWeight: FontWeight.w700, color: Colors.grey); + + @override + Widget getNormalWidget(DateModel dateModel) { + return Container( + margin: EdgeInsets.all(8), + child: new Stack( + alignment: Alignment.center, + children: [ + new Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + //公历 + new Expanded( + child: Center( + child: new Text( + dateModel.day.toString(), + style: dateModel.isCurrentMonth + ? normalTextStyle + : noIsCurrentMonthTextStyle, + ), + ), + ), + ], + ), + ], + ), + ); + } + + @override + Widget getSelectedWidget(DateModel dateModel) { + return Container( +// margin: EdgeInsets.all(8), + decoration: new BoxDecoration( + borderRadius: BorderRadius.all( + Radius.circular(5), + ), + color: Color(0xffFED32B), + ), + child: new Stack( + alignment: Alignment.center, + children: [ + new Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + //公历 + new Expanded( + child: Center( + child: new Text( + dateModel.day.toString(), + style: dateModel.isCurrentMonth + ? normalTextStyle + : noIsCurrentMonthTextStyle, + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/example/lib/custom_sign_page.dart b/example/lib/custom_sign_page.dart index 4ea59cb..74ad880 100644 --- a/example/lib/custom_sign_page.dart +++ b/example/lib/custom_sign_page.dart @@ -113,6 +113,7 @@ class _CustomSignPageState extends State { floatingActionButton: FloatingActionButton( onPressed: () { controller.toggleExpandStatus(); +// controller.changeExtraData({}); }, tooltip: 'Increment', child: Icon(Icons.add), diff --git a/example/lib/default_style_page.dart b/example/lib/default_style_page.dart index 455782f..39945b9 100644 --- a/example/lib/default_style_page.dart +++ b/example/lib/default_style_page.dart @@ -24,10 +24,10 @@ class _DefaultStylePageState extends State { DateTime now = DateTime.now(); controller = new CalendarController( minYear: now.year, - minYearMonth: now.month - 2, + minYearMonth: now.month - 5, maxYear: now.year, - maxYearMonth: now.month + 1, - showMode: Constants.MODE_SHOW_WEEK_AND_MONTH); + maxYearMonth: now.month + 5, + showMode: Constants.MODE_SHOW_MONTH_AND_WEEK); controller.addMonthChangeListener( (year, month) { diff --git a/example/lib/main.dart b/example/lib/main.dart index 9453339..4bcbd68 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,7 @@ import 'package:example/only_week_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +import 'blue_style_page.dart'; import 'custom_sign_page.dart'; import 'custom_style_page.dart'; import 'default_style_page.dart'; @@ -39,6 +40,9 @@ class MyApp extends StatelessWidget { "/only_week_view": (context) => OnlyWeekPage( title: "仅显示周视图", ), + "/blue_style_page":(context)=>BlueStylePage( + title:"蓝色背景Demo" + ) }, title: 'Flutter Demo', theme: ThemeData( @@ -91,9 +95,74 @@ class HomePage extends StatelessWidget { }, child: new Text("仅显示周视图"), ), + new RaisedButton(onPressed: (){ + Navigator.pushNamed(context, "/blue_style_page"); + },child: new Text("蓝色Demo"),) ], ), ), ); } } + +// +//# Desktop Flutter Example +// +//This is the standard Flutter template application, modified to run on desktop. +// +//The `linux` and `windows` directories serve as early prototypes of +//what will eventually become the `flutter create` templates for desktop, and will +//be evolving over time to better reflect that goal. The `macos` directory has +//now become a `flutter create` template, so is largely identical to what that +//command creates. +// +//## Building and Running +// +//See [the main project README](../README.md). +// +//To build without running, use `flutter build macos`/`windows`/`linux` rather than `flutter run`, as with +//a standard Flutter project. +// +//## Dart Differences from Flutter Template +// +//The `main.dart` and `pubspec.yaml` have minor changes to support desktop: +//* `debugDefaultTargetPlatformOverride` is set to avoid 'Unknown platform' +//exceptions. +//* The font is explicitly set to Roboto, and Roboto is bundled via +//`pubspec.yaml`, to ensure that text displays on all platforms. +// +//See the [Flutter Application Requirements section of the Flutter page on +//desktop support](https://github.com/flutter/flutter/wiki/Desktop-shells#flutter-application-requirements) +//for more information. +// +//## Adapting for Another Project +// +//Since `flutter create` is not yet supported for Windows and Linux, the easiest +//way to try out desktop support with an existing Flutter application on those +//platforms is to copy the platform directories from this example; see below for +//details. For macOS, just run `flutter create --macos .` in your project. +// +//Be sure to read the [Flutter page on desktop +//support](https://github.com/flutter/flutter/wiki/Desktop-shells) before trying to +//run an existing project on desktop, especially the [Flutter Application Requirements +//section](https://github.com/flutter/flutter/wiki/Desktop-shells#flutter-application-requirements). +// +//### Coping the Desktop Runners +// +//The 'linux' and 'windows' directories are self-contained, and can be copied to +//an existing Flutter project, enabling `flutter run` for those platforms. +// +//**Be aware that neither the API surface of the Flutter desktop libraries nor the +//interaction between the `flutter` tool and the platform directories is stable, +//and no attempt will be made to provide supported migration paths as things +//change.** You should expect that every time you update Flutter you may have +//to delete your copies of the platform directories and re-copy them from an +//updated version of flutter-desktop-embedding. +// +//### Customizing the Runners +// +//See [Application Customization](App-Customization.md) for premilinary +//documenation on modifying basic application information like name and icon. +// +//If you are building for macOS, you should also read about [managing macOS +//security configurations](../macOS-Security.md). diff --git a/lib/calendar_provider.dart b/lib/calendar_provider.dart index 888ec43..846e4a1 100644 --- a/lib/calendar_provider.dart +++ b/lib/calendar_provider.dart @@ -21,6 +21,15 @@ class CalendarProvider extends ChangeNotifier { double get totalHeight => _totalHeight; + ValueNotifier _generation = + new ValueNotifier(0); //生成的int值,每次变化,都会刷新整个日历。 + + ValueNotifier get generation => _generation; + + set generation(ValueNotifier value) { + _generation = value; + } + set totalHeight(double value) { _totalHeight = value; } @@ -95,27 +104,64 @@ class CalendarProvider extends ChangeNotifier { //配置类也放这里吧,这样的话,所有子树,都可以拿到配置的信息 CalendarConfiguration calendarConfiguration; - void initData( - {Set selectedDateList, - DateModel selectDateModel, - CalendarConfiguration calendarConfiguration}) { + void initData({ + Set selectedDateList, + DateModel selectDateModel, + CalendarConfiguration calendarConfiguration, + EdgeInsetsGeometry padding, + EdgeInsetsGeometry margin, + }) { LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider initData"); if (selectedDateList != null) { this.selectedDateList.addAll(selectedDateList); } this.selectDateModel = selectDateModel; this.calendarConfiguration = calendarConfiguration; + this.calendarConfiguration.padding = padding; + this.calendarConfiguration.margin = margin; //lastClickDateModel,默认是选中的item,如果为空的话,默认是当前的时间 this.lastClickDateModel = selectDateModel != null ? selectDateModel : DateModel.fromDateTime(DateTime.now()) ..day = 15; + //初始化展示状态 if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK || calendarConfiguration.showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) { expandStatus = ValueNotifier(false); } else { expandStatus = ValueNotifier(true); } + //初始化item的大小。如果itemSize为空,默认是宽度/7。网页版的话是高度/7。需要减去padding和margin值 + if (calendarConfiguration.itemSize == null) { + MediaQueryData mediaQueryData = + MediaQueryData.fromWindow(WidgetsBinding.instance.window); + if (mediaQueryData.orientation == Orientation.landscape) { + calendarConfiguration.itemSize = (mediaQueryData.size.height - + calendarConfiguration.padding.horizontal - + calendarConfiguration.margin.horizontal) / + 7; + } else { + calendarConfiguration.itemSize = (mediaQueryData.size.width - + calendarConfiguration.padding.horizontal - + calendarConfiguration.margin.horizontal) / + 7; + } + } else { + //如果指定了itemSize的大小,那就按照itemSize的大小去绘制 + } + + //如果第一个页面展示的是月视图,需要计算下初始化的高度 + if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_MONTH || + calendarConfiguration.showMode == Constants.MODE_SHOW_MONTH_AND_WEEK) { + int lineCount = DateUtil.getMonthViewLineCount( + 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 eeca2fc..798c3cd 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/model/date_model.dart'; +import 'package:flutter/foundation.dart'; /** * 配置信息类 @@ -43,6 +44,8 @@ class CalendarConfiguration { double verticalSpacing; //日历item之间的竖直方向间距,默认10 BoxDecoration boxDecoration; //整体的背景设置 double itemSize; //默认是屏幕宽度/7 + EdgeInsetsGeometry padding; + EdgeInsetsGeometry margin; //支持自定义绘制 DayWidgetBuilder dayWidgetBuilder; //创建日历item @@ -52,11 +55,14 @@ class CalendarConfiguration { * 监听变化 */ //各种事件回调 - OnMonthChange monthChange; //月份切换事件 + OnMonthChange monthChange; //月份切换事件 (已弃用,交给multiMonthChanges来实现) OnCalendarSelect calendarSelect; //点击选择事件 OnMultiSelectOutOfRange multiSelectOutOfRange; //多选超出指定范围 OnMultiSelectOutOfSize multiSelectOutOfSize; //多选超出限制个数 + ObserverList monthChangeListeners = + ObserverList(); //保存多个月份监听的事件 + /** * 下面的信息不是配置的,是根据配置信息进行计算出来的 */ @@ -87,7 +93,10 @@ class CalendarConfiguration { this.monthController, this.weekController, this.verticalSpacing, - this.itemSize,this.showMode}); + this.itemSize, + this.showMode, + this.padding, + this.margin}); @override String toString() { diff --git a/lib/controller.dart b/lib/controller.dart index d61432b..d131673 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -39,8 +39,8 @@ class CalendarController { int maxYear = 2055, int minYearMonth = 1, int maxYearMonth = 12, - int nowYear = -1, - int nowMonth = -1, + int nowYear, + int nowMonth, int minSelectYear = 1971, int minSelectMonth = 1, int minSelectDay = 1, @@ -54,6 +54,13 @@ class CalendarController { double itemSize, Map extraDataMap = EMPTY_MAP}) { LogUtil.log(TAG: this.runtimeType, message: "init CalendarConfiguration"); + //如果没有指定当前月份和年份,默认是当年时间 + if (nowYear == null) { + nowYear = DateTime.now().year; + } + if (nowMonth == null) { + nowMonth = DateTime.now().month; + } calendarConfiguration = CalendarConfiguration( selectMode: selectMode, showMode: showMode, @@ -181,7 +188,8 @@ class CalendarController { //月份切换监听 void addMonthChangeListener(OnMonthChange listener) { - this.calendarConfiguration.monthChange = listener; +// this.calendarConfiguration.monthChange = listener; + this.calendarConfiguration.monthChangeListeners.add(listener); } //点击选择监听 @@ -233,9 +241,11 @@ class CalendarController { } else { calendarProvider.calendarConfiguration.monthController .previousPage(duration: DEFAULT_DURATION, curve: Curves.ease); - calendarProvider.calendarConfiguration.monthChange( - monthList[currentIndex - 1].year, - monthList[currentIndex - 1].month); + calendarProvider.calendarConfiguration.monthChangeListeners + .forEach((listener) { + listener(monthList[currentIndex - 1].year, + monthList[currentIndex - 1].month); + }); DateModel temp = new DateModel(); temp.year = monthList[currentIndex].year; temp.month = monthList[currentIndex].month; @@ -272,9 +282,12 @@ class CalendarController { } else { calendarProvider.calendarConfiguration.monthController .nextPage(duration: DEFAULT_DURATION, curve: Curves.ease); - calendarProvider.calendarConfiguration.monthChange( - monthList[currentIndex + 1].year, - monthList[currentIndex + 1].month); + calendarProvider.calendarConfiguration.monthChangeListeners + .forEach((listener) { + listener(monthList[currentIndex + 1].year, + monthList[currentIndex + 1].month); + }); + DateModel temp = new DateModel(); temp.year = monthList[currentIndex].year; temp.month = monthList[currentIndex].month; diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index b403203..f5d6c7b 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -19,11 +19,19 @@ class CalendarViewWidget extends StatefulWidget { //整体的背景设置 BoxDecoration boxDecoration; + //日历的padding和margin + EdgeInsetsGeometry padding; + EdgeInsetsGeometry margin; + //控制器 final CalendarController calendarController; CalendarViewWidget( - {Key key, @required this.calendarController, this.boxDecoration}) + {Key key, + @required this.calendarController, + this.boxDecoration, + this.padding = EdgeInsets.zero, + this.margin = EdgeInsets.zero}) : super(key: key); @override @@ -35,7 +43,9 @@ class _CalendarViewWidgetState extends State { void initState() { //初始化一些数据,一些跟状态有关的要放到provider中 widget.calendarController.calendarProvider.initData( - calendarConfiguration: widget.calendarController.calendarConfiguration); + calendarConfiguration: widget.calendarController.calendarConfiguration, + padding: widget.padding, + margin: widget.margin); super.initState(); } @@ -53,6 +63,8 @@ class _CalendarViewWidgetState extends State { child: Container( //外部可以自定义背景设置 decoration: widget.boxDecoration, + padding: widget.padding, + margin: widget.margin, //使用const,保证外界的setState不会刷新日历这个widget child: CalendarContainer(widget.calendarController)), ); @@ -128,47 +140,32 @@ class CalendarContainerState extends State } }); }); - }else{ - index=0; - + } else { + index = 0; } -// widget.calendarController.addMonthChangeListener((year, month) { -// if (widget.calendarController.calendarProvider.calendarConfiguration -// .showMode != -// Constants.MODE_SHOW_ONLY_WEEK) { -// //月份切换的时候,如果高度发生变化的话,需要setState使高度整体自适应 -// int lineCount = DateUtil.getMonthViewLineCount(year, month); -// double newHeight = itemHeight * lineCount + -// calendarProvider.calendarConfiguration.verticalSpacing * -// (lineCount - 1); -// if (totalHeight.toInt() != newHeight.toInt()) { -// LogUtil.log( -// TAG: this.runtimeType, -// message: "totalHeight:$totalHeight,newHeight:$newHeight"); -// -// LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); -// setState(() { -// totalHeight = newHeight; -// }); -// } -// } -// }); - - //暂时先这样写死,提前计算布局的高度,不然会出现问题:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand. - - MediaQueryData mediaQueryData = - MediaQueryData.fromWindow(WidgetsBinding.instance.window); - - //如果itemSize为空,默认是宽度/7。网页版的话是高度/7 - itemHeight = calendarProvider.calendarConfiguration.itemSize != null - ? calendarProvider.calendarConfiguration.itemSize - : mediaQueryData.orientation == Orientation.landscape - ? mediaQueryData.size.height / 7 - : mediaQueryData.size.width / 7; - - calendarProvider.totalHeight = itemHeight * 6 + - calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1); + widget.calendarController.addMonthChangeListener((year, month) { + if (widget.calendarController.calendarProvider.calendarConfiguration + .showMode != + Constants.MODE_SHOW_ONLY_WEEK) { + //月份切换的时候,如果高度发生变化的话,需要setState使高度整体自适应 + int lineCount = DateUtil.getMonthViewLineCount(year, month); + double newHeight = itemHeight * (lineCount) + + calendarProvider.calendarConfiguration.verticalSpacing * + (lineCount - 1); + LogUtil.log( + TAG: this.runtimeType, + message: "totalHeight:$totalHeight,newHeight:$newHeight"); + if (totalHeight.toInt() != newHeight.toInt()) { + LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); + setState(() { + totalHeight = newHeight; + }); + } + } + }); + + itemHeight = calendarProvider.calendarConfiguration.itemSize; totalHeight = calendarProvider.totalHeight; } @@ -180,9 +177,6 @@ class CalendarContainerState extends State @override Widget build(BuildContext context) { LogUtil.log(TAG: this.runtimeType, message: "CalendarContainerState build"); - //暂时先这样写死,提前计算布局的高度,不然会出现问题:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand. -// itemHeight = calendarProvider.calendarConfiguration.itemSize ?? -// MediaQuery.of(context).size.width / 7; return Container( width: itemHeight * 7, child: new Column( diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 019ea69..6b3a8d5 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -117,6 +117,7 @@ class _MonthViewState extends State return new GridView.builder( addAutomaticKeepAlives: true, + padding: EdgeInsets.zero, physics: const NeverScrollableScrollPhysics(), gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 7, mainAxisSpacing: configuration.verticalSpacing), diff --git a/lib/widget/month_view_pager.dart b/lib/widget/month_view_pager.dart index 9fceaab..358d442 100644 --- a/lib/widget/month_view_pager.dart +++ b/lib/widget/month_view_pager.dart @@ -15,7 +15,8 @@ class MonthViewPager extends StatefulWidget { _MonthViewPagerState createState() => _MonthViewPagerState(); } -class _MonthViewPagerState extends State with AutomaticKeepAliveClientMixin{ +class _MonthViewPagerState extends State + with AutomaticKeepAliveClientMixin { CalendarProvider calendarProvider; @override @@ -71,7 +72,9 @@ class _MonthViewPagerState extends State with AutomaticKeepAlive } //月份的变化 DateModel dateModel = configuration.monthList[position]; - configuration.monthChange(dateModel.year, dateModel.month); + configuration.monthChangeListeners.forEach((listener) { + listener(dateModel.year, dateModel.month); + }); //用来保存临时变量,用于月视图切换到周视图的时候,默认是显示中间的一周 if (calendarProvider.lastClickDateModel != null || calendarProvider.lastClickDateModel.month != dateModel.month) { @@ -81,24 +84,6 @@ class _MonthViewPagerState extends State with AutomaticKeepAlive temp.day = configuration.monthList[position].day + 14; calendarProvider.lastClickDateModel = temp; } - - //计算下高度,使PageView自适应高度 - if (calendarProvider.calendarConfiguration.showMode != - Constants.MODE_SHOW_ONLY_WEEK) { - //月份切换的时候,如果高度发生变化的话,需要setState使高度整体自适应 -// int lineCount = -// DateUtil.getMonthViewLineCount(dateModel.year, dateModel.month); -// double newHeight = (calendarProvider.calendarConfiguration.itemSize ?? -// MediaQuery.of(context).size.width / 7) * -// lineCount + -// calendarProvider.calendarConfiguration.verticalSpacing * -// (lineCount - 1); -// if (calendarProvider.totalHeight.toInt() != newHeight.toInt()) { -// LogUtil.log(TAG: this.runtimeType, message: "月份视图高度发生变化"); -// calendarProvider.totalHeight = newHeight; -//// calendarProvider.changeTotalHeight(newHeight); -// } - } }, controller: configuration.monthController, itemBuilder: (context, index) { diff --git a/lib/widget/week_view_pager.dart b/lib/widget/week_view_pager.dart index 0ba52e8..ef9f06d 100644 --- a/lib/widget/week_view_pager.dart +++ b/lib/widget/week_view_pager.dart @@ -14,7 +14,8 @@ class WeekViewPager extends StatefulWidget { _WeekViewPagerState createState() => _WeekViewPagerState(); } -class _WeekViewPagerState extends State with AutomaticKeepAliveClientMixin{ +class _WeekViewPagerState extends State + with AutomaticKeepAliveClientMixin { int lastMonth; //保存上一个月份,不然不知道月份发生了变化 CalendarProvider calendarProvider; @@ -64,8 +65,9 @@ class _WeekViewPagerState extends State with AutomaticKeepAliveCl TAG: this.runtimeType, message: "WeekViewPager PageView monthChange:currentMonth:${currentMonth}"); - configuration.monthChange( - firstDayOfWeek.year, firstDayOfWeek.month); + configuration.monthChangeListeners.forEach((listener) { + listener(firstDayOfWeek.year, firstDayOfWeek.month); + }); lastMonth = currentMonth; if (calendarProvider.lastClickDateModel == null || calendarProvider.lastClickDateModel.month != currentMonth) { From c223b3ba78a69c8487de6fc0fd11e08aa94f8b71 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 17:57:22 +0800 Subject: [PATCH 09/25] =?UTF-8?q?readme=E6=96=87=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 17 ++- README.md | 329 +++++++++------------------------------------------ README_en.md | 113 ++++++++++++++++++ 3 files changed, 182 insertions(+), 277 deletions(-) create mode 100644 README_en.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 38d5db9..8ff01c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,21 @@ -## [1.0.0] - 2019/9/22 -* 重构日历的代码 +### 近期修改 + + +### [2.0.0] - 2019/11/01 +* 日历支持padding和margin属性,item的大小计算修改 +* 实现日历整体自适应高度 +* controller提供changeExtraDataMap的方法,可以随时动态的修改自定义数据extraDataMap +* 支持显示月视图和周视图的情况,优先显示周视图,MODE_SHOW_WEEK_AND_MONTH +* 支持verticalSpacing和itemSize属性 +### [1.0.0] - 2019/10/10 +* 重构日历的代码,进行性能优化 * 创建configuration类,将配置的信息放到这里 * 引入provider状态管理,避免深层嵌套传递信息 * 实现周视图,并实现周视图和月视图之间的联动 * DateModel增加isCurrentMonth,用于绘制月视图可以屏蔽一些非当前月份的日子,前面几天或者后面几天的isCurrentMonth是为false的。 +### [0.0.1] - 2019/5/19. -## [0.0.1] - 2019/5/19. - -## 主要功能 * 支持公历,农历,节气,传统节日,常用节假日 * 日期范围设置,默认支持的最大日期范围为1971.01-2055.12 * 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰 diff --git a/README.md b/README.md index e62c030..020a83d 100644 --- a/README.md +++ b/README.md @@ -3,25 +3,20 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 -## 介绍 -之前写了一个Flutter日历的开源库,最近增加了一些功能,并且对代码进行了一下重构。(之前的代码写得真的是****,没搞状态框架,还各种嵌套代码) +### Language: [English](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/README_en.md)|中文简体 -## 示例 +* 概述 +* 在线Demo +* 效果图 +* 快速使用 +* 2.0版本 +* 注意事项 +* 主要Api文档 -日历支持web预览:[点击此处进入预览](https://lxd312569496.github.io/flutter_custom_calendar/#/) - - - - - - - - +### 概述 - -## 主要功能 * 支持公历,农历,节气,传统节日,常用节假日 * 日期范围设置,默认支持的最大日期范围为1971.01-2055.12 * 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰 @@ -30,296 +25,86 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 * 自定义日历Item,支持组合widget的方式和利用canvas绘制的方式 * 自定义顶部的WeekBar * 根据实际场景,可以给Item添加自定义的额外数据,实现各种额外的功能。比如实现进度条风格的日历,实现日历的各种标记 -* 支持周视图的展示 -* 支持月份视图和星期视图的展示与切换联动 +* 支持周视图的展示,支持月份视图和星期视图的展示与切换联动 -## 近期修改 -### [1.0.0] - 2019/10/10 -* 重构日历的代码,进行性能优化 -* 创建configuration类,将配置的信息放到这里 -* 引入provider状态管理,避免深层嵌套传递信息 -* 实现周视图,并实现周视图和月视图之间的联动 -* DateModel增加isCurrentMonth,用于绘制月视图可以屏蔽一些非当前月份的日子,前面几天或者后面几天的isCurrentMonth是为false的。 +### 在线Demo -### [0.0.1] - 2019/5/19. +日历支持web预览:[点击此处进入预览](https://lxd312569496.github.io/flutter_custom_calendar/#/) + + +### 效果图 + + + + + + + + + -* 支持公历,农历,节气,传统节日,常用节假日 -* 日期范围设置,默认支持的最大日期范围为1971.01-2055.12 -* 禁用日期范围设置,比如想实现某范围的日期内可以点击,范围外的日期置灰 -* 支持单选、多选模式,提供多选超过限制个数的回调和多选超过指定范围的回调。 -* 跳转到指定日期,默认支持动画切换 -* 自定义日历Item,支持组合widget的方式和利用canvas绘制的方式 -* 自定义顶部的WeekBar -* 可以给Item添加自定义的额外数据,实现各种额外的功能。比如实现进度条风格的日历 ## 使用 -在pubspec.yaml添加依赖: +1.在pubspec.yaml文件里面添加依赖: ``` flutter_custom_calendar: git: url: https://github.com/LXD312569496/flutter_custom_calendar.git ``` -引入flutter_custom_calendar,就可以使用CalendarViewWidget,配置CalendarController就可以了。 + +2.导入flutter_custom_calendar库 ``` import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; - -CalendarViewWidget({@required this.calendarController, this.boxDecoration}); ``` -* boxDecoration用来配置整体的背景 -* 利用CalendarController来配置一些数据,并且可以通过CalendarController进行一些操作或者事件监听,比如滚动到下一个月,获取当前被选中的Item等等。 - -## 配置CalendarController - -下面是CalendarController中一些支持自定义配置的属性。不配置的话,会有对应的默认值。(配置现在都是在controller这里进行配置的,内部会将配置的数据抽成Configuration类) - -配置的含义主要包括了3个方面的配置。 -* 一个是显示日历所需要的相关数据, -* 一个是显示日历的自定义UI的相关配置, -* 一个是对日历的监听事件进行配置。 - +3.创建CalendarViewWidget对象,配置CalendarController ``` - //构造函数 - CalendarController( - {int selectMode = Constants.MODE_SINGLE_SELECT, - int showMode = Constants.MODE_SHOW_ONLY_MONTH, - bool expandStatus = true, - 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 selectedDateTimeList = EMPTY_SET, - DateModel selectDateModel, - int maxMultiSelectCount = 9999, - double verticalSpacing = 10, - bool enableExpand = true, - Map extraDataMap = EMPTY_MAP}) - +CalendarController controller= new CalendarController( + minYear: 2018, + minYearMonth: 1, + maxYear: 2020, + maxYearMonth: 12, + showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK); +CalendarViewWidget calendar= CalendarViewWidget( + calendarController: controller, + ), ``` -### 数据方面的配置 - -属性 | 含义 | 默认值 -:-: | :-: | :-: -selectMode | 选择模式,表示单选或者多选 | 默认是单选
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2; -showMode|展示模式| 默认是只展示月视图
static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图
static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图
static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持月和星期视图切换 -minYear | 日历显示的最小年份| 1971 -maxYear | 日历显示的最大年份| 2055 -minYearMonth | 日历显示的最小年份的月份| 1 -maxYearMonth | 日历显示的最大年份的月份| 12 -nowYear | 日历显示的当前的年份| -1 -nowMonth | 日历显示的当前的月份| -1 -minSelectYear | 可以选择的最小年份| 1971 -minSelectMonth | 可以选择的最小年份的月份| 1 -minSelectDay | 可以选择的最小月份的日子| 1 -maxSelectYear | 可以选择的最大年份| 2055 -maxSelectMonth | 可以选择的最大年份的月份| 12 -maxSelectDay | 可以选择的最大月份的日子| 30,注意:不能超过对应月份的总天数 -selectedDateList | 被选中的日期,用于多选| 默认为空Set, Set selectedDateList = new Set() -selectDateModel | 当前选择项,用于单选| 默认为空 -maxMultiSelectCount | 多选,最多选多少个| hhh -extraDataMap | 自定义额外的数据| 默认为空Map,Map extraDataMap = new Map() - - -### UI绘制相关的配置 - -属性 | 含义 | 默认值 -:-: | :-: | :-: -weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 -dayWidgetBuilder | 创建日历item | 默认样式 -verticalSpacing|日历item之间的竖直方向间距|默认10 -boxDecoration |整体的背景设置| -itemSize| 每个item的边长|默认是屏幕宽度/7| - - -### 事件监听的配置 - -方法 | 含义 | 默认值 -:-: | :-: | :-: -void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 | -void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 | -void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 | -void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 | -void addExpandChangeListener(ValueChanged expandChange)|监听日历的展开收缩状态| - -## 利用controller来控制日历的切换,支持配置动画 - -方法 | 含义 | 默认值 -:-: | :-: | :-: -Future previousPage()|滑动到上一个页面,会自动根据当前的展开状态,滑动到上一个月或者上一个星期。如果已经在第一个页面,没有上一个页面,就会返回false,其他情况返回true| -Future nextPage()|滑动到下一个页面,会自动根据当前的展开状态,滑动到下一个月或者下一个星期。如果已经在最后一个页面,没有下一个页面,就会返回false,其他情况返回true| -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()|切换到上一个月份| -void toggleExpandStatus()|切换展开状态| - - -## 利用controller来获取日历的一些数据信息 - -方法 | 含义 | 默认值 -:-: | :-: | :-: -DateTime getCurrentMonth()|获取当前的月份| -Set getMultiSelectCalendar()|获取被选中的日期,多选| -DateModel getSingleSelectCalendar()|获取被选中的日期,单选| - - -## 如何自定义UI - -包括自定义WeekBar、自定义日历Item,默认使用的都是DefaultXXXWidget。 +* boxDecoration用来配置整体的背景 +* 利用CalendarController来配置一些数据,并且可以通过CalendarController进行一些操作或者事件监听,比如滚动到下一个月,获取当前被选中的Item等等。 -只要继承对应的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就行。 +4.操作日历 ``` -class DefaultCombineDayWidget extends BaseCombineDayWidget { - DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); - - @override - Widget getNormalWidget(DateModel dateModel) { - //实现默认状态下的UI - } - - @override - Widget getSelectedWidget(DateModel dateModel) { - //绘制被选中的UI - } -} +controller.toggleExpandStatus();//月视图和周视图的切换 ``` - -* 继承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); - } -} +controller.previousPage();//操作日历切换到上一页 ``` -### 根据实际场景,自定义额外的数据extraData - -#### 自定义每个item的进度条数据 - ``` - //外部处理每个dateModel所对应的进度 - Map progressMap = { - DateModel.fromDateTime(temp.add(Duration(days: 1))): 0, - DateModel.fromDateTime(temp.add(Duration(days: 2))): 20, - DateModel.fromDateTime(temp.add(Duration(days: 3))): 40, - DateModel.fromDateTime(temp.add(Duration(days: 4))): 60, - DateModel.fromDateTime(temp.add(Duration(days: 5))): 80, - DateModel.fromDateTime(temp.add(Duration(days: 6))): 100, - }; - //创建CalendarController对象的时候,将extraDataMap赋值就行了 - new CalendarController( - extraDataMap: progressMap) - //绘制DayWidget的时候,可以直接从dateModel的extraData对象中拿到想要的数据 - int progress = dateModel.extraData; +controller.nextPage();//操作日历切换到下一页 ``` -#### 自定义各种标记 -``` - //外部处理每个dateModel所对应的标记 - Map customExtraData = { - DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假", - DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游", - DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事", - DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班", - DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假", - DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事", - DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班", - }; - //创建CalendarController对象的时候,将extraDataMap赋值就行了 - new CalendarController( - extraDataMap: customExtraData) - //绘制DayWidget的时候,可以直接从dateModel的extraData对象中拿到想要的数据 - String data = dateModel.extraData; -``` +## 2.0版本 +主要改动: +* UI配置相关的参数,移动到CalendarView的构造方法里面(旧版本是在controller里面配置) +* 日历支持padding和margin属性,item的大小计算修改 +* 实现日历整体自适应高度 +* controller提供changeExtraDataMap的方法,可以随时动态的修改自定义数据extraDataMap +* 支持显示月视图和周视图的情况,优先显示周视图,MODE_SHOW_WEEK_AND_MONTH +* 支持verticalSpacing和itemSize属性 +## 注意事项 -## DateModel实体类 -日历所用的日期的实体类DateModel,有下面这些属性。可以在自定义绘制DayWidget的时候,根据相应的属性,进行判断后,绘制相应的UI。 +* 如果使用2.0之前的版本,则需要将UI配置相关的参数,移动到CalendarView的构造方法里面(旧版本是在controller里面配置) +* 暂时没有发现其他问题,如果有其他问题,可以跟我说一下。 +* 如果你用这个库做了日历,可以将展示结果分享给我,我贴到文档上进行展示 -属性|含义|类型|默认值 -:-: | :-: | :-: |:-: -year|年份|int| -month|月份|int| -day|日期|int|默认为1 -lunarYear|农历年份|int| -lunarMonth|农历月份|int| -lunarDay|农历日期|int| -lunarString|农历字符串|String| -solarTerm|24节气|String| -gregorianFestival|gregorianFestival|String| -traditionFestival|传统农历节日|String| -isCurrentDay|是否是今天|bool|false -isLeapYear|是否是闰年|bool|false -isWeekend|是否是周末|bool|false -isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false -isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false -extraData|自定义的额外数据|Object|默认为空 +## 主要API文档 +[API Documentation](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/API.md) -方法|含义| -:-: | :-: | -DateTime getDateTime()|将DateModel转化成DateTime -DateModel fromDateTime(DateTime dateTime)|根据DateTime创建对应的model,并初始化农历和传统节日等信息 -bool operator ==(Object other)|重写==方法,可以判断两个dateModel是否是同一天 \ No newline at end of file diff --git a/README_en.md b/README_en.md new file mode 100644 index 0000000..638ddf0 --- /dev/null +++ b/README_en.md @@ -0,0 +1,113 @@ + +## FlutterCalendarWidget + +Flutter上的一个日历控件,可以定制成自己想要的样子。 +A calendar widget in flutter,you can design what you want to show! + + +### Language: 中文简体|[English](https://lxd312569496.github.io/flutter_custom_calendar/) + +* Overview +* Online Demo +* Example +* Getting Started +* 2.0 version +* matters needing attention +* API Documentation + + + +### Overview + +* Support the Gregorian calendar, lunar calendar, solar terms, traditional festivals and common holidays +* Date range setting, the maximum date range supported by default is 1971.01-2055.12 +* Disable date range settings. For example, you can click within a range of dates and gray the dates outside the range +* Support single selection and multiple selection modes, and provide multiple selection of callbacks exceeding the limit and multiple selection of callbacks exceeding the specified range. +* Jump to the specified date. Animation switching is supported by default +* Custom Calendar items, support the way of combining widgets and drawing with canvas +* Customize the weekbar at the top +* According to the actual scene, you can add custom additional data to the item to realize various additional functions. For example, to realize the calendar of progress bar style and various marks of calendar +* Support weekly view display, monthly view and weekly view display and switching linkage + +### Online Demo + +Calendar supports web Preview:[Click here for preview](https://lxd312569496.github.io/flutter_custom_calendar/#/) + + +### Example + + + + + + + + + + + +## Getting Started + +1.add dependencies into you project pubspec.yaml file: +``` +flutter_custom_calendar: + git: + url: https://github.com/LXD312569496/flutter_custom_calendar.git +``` + +2.import flutter_custom_calendar lib +``` +import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; +``` + +3.create CalendarViewWidget object,profile CalendarController +``` +CalendarController controller= new CalendarController( + minYear: 2018, + minYearMonth: 1, + maxYear: 2020, + maxYearMonth: 12, + showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK); +CalendarViewWidget calendar= CalendarViewWidget( + calendarController: controller, + ), +``` + +4.operate controller +``` +controller.toggleExpandStatus();//Switch between month view and week view +``` + +``` +controller.previousPage();//Action calendar switch to previous page +``` + +``` +controller.nextPage();//Action calendar switch to next page + +``` + + +## 2.0 version +Major changes: +* The UI configuration related parameters are moved to the calendar view construction method (the old version is configured in the controller) +* Calendar supports padding and margin attributes, and item size calculation and modification. +* Realize the overall adaptive height of calendar +* The controller provides the method of changing extradatamap, which can dynamically modify the customized data extradatamap at any time. +* It supports the display of monthly view and weekly view, with weekly view as the priority, and mode "show" week "and" month " +* Supports verticalspacing and itemsize properties + + +## matters needing attention + +* If you use the version before 2.0, you need to move the UI configuration related parameters to the calendar view construction method (the old version is configured in the controller). +* I haven't found any other problems for the time being. If you have any, please let me know. +* If you use this library to make a calendar, you can share the display results with me, and I will paste them on the document for display. + + + +## API Documentation + +[API Documentation](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/API.md) + + From d0b0d88ca5fd67362005951dd46594aba880b471 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 17:58:31 +0800 Subject: [PATCH 10/25] =?UTF-8?q?=E6=96=87=E6=A1=A3=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=EF=BC=8C=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API.md | 318 +++++++++++++++++++++++ example/lib/blue_style_page.dart | 24 +- example/lib/custom_sign_page.dart | 13 +- example/lib/custom_style_page.dart | 15 +- example/lib/default_style_page.dart | 2 +- example/lib/main.dart | 21 +- example/lib/multi_select_style_page.dart | 26 +- example/lib/only_week_page.dart | 2 +- example/lib/progress_style_page.dart | 18 +- example/lib/red_style_page.dart | 236 +++++++++++++++++ lib/calendar_provider.dart | 22 +- lib/configuration.dart | 2 +- lib/constants/constants.dart | 2 +- lib/controller.dart | 50 ++-- lib/utils/lunar_util.dart | 6 +- lib/widget/calendar_view.dart | 34 ++- lib/widget/default_week_bar.dart | 2 +- lib/widget/month_view.dart | 6 +- lib/widget/week_view.dart | 2 +- 19 files changed, 694 insertions(+), 107 deletions(-) create mode 100644 API.md create mode 100644 example/lib/red_style_page.dart diff --git a/API.md b/API.md new file mode 100644 index 0000000..4c2cd88 --- /dev/null +++ b/API.md @@ -0,0 +1,318 @@ + +## 主要Api文档 + +### 配置日历的UI + +日历UI相关的配置是在CalendarViewWidget的构造函数里面进行配置就行了。 +``` + CalendarViewWidget( + {Key key, + this.dayWidgetBuilder = defaultCustomDayWidget, + this.weekBarItemWidgetBuilder = defaultWeekBarWidget, + @required this.calendarController, + this.boxDecoration, + this.padding = EdgeInsets.zero, + this.margin = EdgeInsets.zero, + this.verticalSpacing = 10, + this.itemSize}) + : super(key: key); +``` +#### 参数说明 + +属性 | 含义 | 默认值 +:-: | :-: | :-: +weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 +dayWidgetBuilder | 创建日历item | 默认样式 +verticalSpacing|日历item之间的竖直方向间距|默认10 +boxDecoration |整体的背景设置|默认为空 +itemSize| 每个item的边长|手机默认是屏幕宽度/7,网页默认屏幕高度/7| +padding|日历的padding |默认为EdgeInsets.zero +margin| 日历的padding|默认为EdgeInsets.zero + + + +### 配置Controller +两个作用: +一个是显示日历所需要的相关数据,是在controller里面进行配置的。 +一个是可以利用controller添加事件监听,使用controller进行操作日历 + + +``` + //构造函数 + CalendarController( + {int selectMode = CalendarConstants.MODE_SINGLE_SELECT, + int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH, + int minYear = 1971, + int maxYear = 2055, + int minYearMonth = 1, + int maxYearMonth = 12, + int nowYear, + int nowMonth, + int minSelectYear = 1971, + int minSelectMonth = 1, + int minSelectDay = 1, + int maxSelectYear = 2055, + int maxSelectMonth = 12, + int maxSelectDay = 30, + Set selectedDateTimeList = EMPTY_SET, + DateModel selectDateModel, + int maxMultiSelectCount = 9999, + Map extraDataMap = EMPTY_MAP}) +``` + +#### 通用参数说明 + +属性 | 含义 | 默认值 +:-: | :-: | :-: +selectMode | 选择模式,表示单选或者多选 | 默认是单选
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2; +showMode|展示模式| 默认是只展示月视图
static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图
static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图
static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图
static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 +minYear | 日历显示的最小年份| 1971 +maxYear | 日历显示的最大年份| 2055 +minYearMonth | 日历显示的最小年份的月份| 1 +maxYearMonth | 日历显示的最大年份的月份| 12 +nowYear | 日历显示的当前的年份| -1 +nowMonth | 日历显示的当前的月份| -1 +minSelectYear | 可以选择的最小年份| 1971 +minSelectMonth | 可以选择的最小年份的月份| 1 +minSelectDay | 可以选择的最小月份的日子| 1 +maxSelectYear | 可以选择的最大年份| 2055 +maxSelectMonth | 可以选择的最大年份的月份| 12 +maxSelectDay | 可以选择的最大月份的日子| 30,注意:不能超过对应月份的总天数 +selectedDateList | 被选中的日期,用于多选| 默认为空Set, Set selectedDateList = new Set() +selectDateModel | 当前选择项,用于单选| 默认为空 +maxMultiSelectCount | 多选,最多选多少个| hhh +extraDataMap | 自定义额外的数据| 默认为空Map,Map extraDataMap = new Map() + + +#### 给controller添加事件监听 + +方法 | 含义 | 默认值 +:-: | :-: | :-: +void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 | +void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 | +void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 | +void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 | +void addExpandChangeListener(ValueChanged expandChange)|监听日历的展开收缩状态| + +#### 利用controller来控制日历的切换,支持配置动画 + +方法 | 含义 | 默认值 +:-: | :-: | :-: +Future previousPage()|滑动到上一个页面,会自动根据当前的展开状态,滑动到上一个月或者上一个星期。如果已经在第一个页面,没有上一个页面,就会返回false,其他情况返回true| +Future nextPage()|滑动到下一个页面,会自动根据当前的展开状态,滑动到下一个月或者下一个星期。如果已经在最后一个页面,没有下一个页面,就会返回false,其他情况返回true| +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()|切换到上一个月份| +void toggleExpandStatus()|切换展开状态| +void changeExtraData(Map newMap)|修改自定义的额外数据并刷新日历| + + +#### 利用controller来获取当前日历的状态和数据 + +方法 | 含义 | 默认值 +:-: | :-: | :-: +DateTime getCurrentMonth()|获取当前的月份| +Set 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, + ), + ); + } +} +``` +第二种做法,你也可以直接重写build方法,进行更加的自定义绘制。 + +``` +class CustomStyleWeekBarItem extends BaseWeekBar { + List weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"]; + + //可以直接重写build方法,weekbar底部添加下划线 + @override + Widget build(BuildContext context) { + List children = List(); + + var items = getWeekDayWidget(); + children.add(Row( + children: items, + )); + children.add(Divider( + color: Colors.grey, + )); + return Column( + children: children, + ); + } + + @override + Widget getWeekBarItem(int index) { + return new Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: new Center( + child: new Text( + weekList[index], + style: + TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)), + ), + ), + ); + } +} +``` + + +#### 自定义日历Item: +提供两种方法,一种是利用组合widget的方式来创建,一种是利用Canvas来自定义绘制Item。最后只需要在CalendarController的构造参数中进行配置就可以了。 +* 利用组合widget的方式来创建:继承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 + } +} +``` + + +* 利用Canvas来自定义绘制,继承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); + } +} +``` + +### 根据实际场景,自定义额外的数据extraData + +#### 实现进度条样式的日历 + +我们可以自定义每个item的进度条数据,保存到map中,最后赋值给controller的extraDataMap。 +``` + //外部处理每个dateModel所对应的进度 + Map progressMap = { + DateModel.fromDateTime(temp.add(Duration(days: 1))): 0, + DateModel.fromDateTime(temp.add(Duration(days: 2))): 20, + DateModel.fromDateTime(temp.add(Duration(days: 3))): 40, + DateModel.fromDateTime(temp.add(Duration(days: 4))): 60, + DateModel.fromDateTime(temp.add(Duration(days: 5))): 80, + DateModel.fromDateTime(temp.add(Duration(days: 6))): 100, + }; + //创建CalendarController对象的时候,将extraDataMap赋值就行了 + new CalendarController( + extraDataMap: progressMap) + //绘制DayWidget的时候,可以直接从dateModel的extraData对象中拿到想要的数据 + int progress = dateModel.extraData; +``` + +#### 实现自定义各种标记的日历 +``` + //外部处理每个dateModel所对应的标记 + Map customExtraData = { + DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班", + }; + //创建CalendarController对象的时候,将extraDataMap赋值就行了 + new CalendarController( + extraDataMap: customExtraData) + //绘制DayWidget的时候,可以直接从dateModel的extraData对象中拿到想要的数据 + String data = dateModel.extraData; +``` + +#### 手动修改自定义的数据 +当自定义的数据发生变化的时候,可以使用controller的changeExtraData(Map newMap)方法, +日历会自动刷新,根据新的额外数据进行绘制。 +``` + //可以动态修改extraDataMap + void changeExtraData(Map newMap) { + this.calendarConfiguration.extraDataMap = newMap; + this.calendarProvider.generation.value++; + } +``` + +### DateModel实体类 +日历所用的日期的实体类DateModel,有下面这些属性。可以在自定义绘制DayWidget的时候,根据相应的属性,进行判断后,绘制相应的UI。 + +属性|含义|类型|默认值 +:-: | :-: | :-: |:-: +year|年份|int| +month|月份|int| +day|日期|int|默认为1 +lunarYear|农历年份|int| +lunarMonth|农历月份|int| +lunarDay|农历日期|int| +lunarString|农历字符串|String| +solarTerm|24节气|String| +gregorianFestival|gregorianFestival|String| +traditionFestival|传统农历节日|String| +isCurrentDay|是否是今天|bool|false +isLeapYear|是否是闰年|bool|false +isWeekend|是否是周末|bool|false +isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false +isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false +extraData|自定义的额外数据|Object|默认为空 +isCurrentMonth|是否是当前月份|bool| + + +方法|含义| +:-: | :-: | +DateTime getDateTime()|将DateModel转化成DateTime +DateModel fromDateTime(DateTime dateTime)|根据DateTime创建对应的model,并初始化农历和传统节日等信息 +bool operator ==(Object other)|重写==方法,可以判断两个dateModel是否是同一天 \ No newline at end of file diff --git a/example/lib/blue_style_page.dart b/example/lib/blue_style_page.dart index ab4a71f..297c2f0 100644 --- a/example/lib/blue_style_page.dart +++ b/example/lib/blue_style_page.dart @@ -3,9 +3,7 @@ import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; import 'package:flutter_custom_calendar/style/style.dart'; import 'package:random_pk/random_pk.dart'; -/** - * 自定义一些额外的数据,实现标记功能 - */ + class BlueStylePage extends StatefulWidget { BlueStylePage({Key key, this.title}) : super(key: key); @@ -26,13 +24,8 @@ class _BlueStylePageState extends State { @override void initState() { controller = new CalendarController( - weekBarItemWidgetBuilder: () { - return CustomStyleWeekBarItem(); - }, - dayWidgetBuilder: (dateModel) { - return CustomStyleDayWidget(dateModel); - }, - showMode: Constants.MODE_SHOW_MONTH_AND_WEEK, + + showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK, extraDataMap: customExtraData); controller.addMonthChangeListener( @@ -56,6 +49,12 @@ class _BlueStylePageState extends State { @override Widget build(BuildContext context) { var calendarWidget = CalendarViewWidget( + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }, calendarController: controller, boxDecoration: BoxDecoration( borderRadius: BorderRadius.only( @@ -126,7 +125,10 @@ class _BlueStylePageState extends State { ValueListenableBuilder( valueListenable: selectText, builder: (context, value, child) { - return new Text(selectText.value); + return Padding( + padding: const EdgeInsets.all(20.0), + child: new Text(selectText.value), + ); }), ], ), diff --git a/example/lib/custom_sign_page.dart b/example/lib/custom_sign_page.dart index 74ad880..b4df94c 100644 --- a/example/lib/custom_sign_page.dart +++ b/example/lib/custom_sign_page.dart @@ -44,12 +44,7 @@ class _CustomSignPageState extends State { @override void initState() { controller = new CalendarController( - weekBarItemWidgetBuilder: () { - return CustomStyleWeekBarItem(); - }, - dayWidgetBuilder: (dateModel) { - return CustomStyleDayWidget(dateModel); - }, + extraDataMap: customExtraData); controller.addMonthChangeListener( @@ -101,6 +96,12 @@ class _CustomSignPageState extends State { ), CalendarViewWidget( calendarController: controller, + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }, ), ValueListenableBuilder( valueListenable: selectText, diff --git a/example/lib/custom_style_page.dart b/example/lib/custom_style_page.dart index 711c058..6f587ca 100644 --- a/example/lib/custom_style_page.dart +++ b/example/lib/custom_style_page.dart @@ -21,11 +21,7 @@ class _CustomStylePageState extends State { @override void initState() { - controller = new CalendarController(weekBarItemWidgetBuilder: () { - return CustomStyleWeekBarItem(); - }, dayWidgetBuilder: (dateModel) { - return CustomStyleDayWidget(dateModel); - }); + controller = new CalendarController(); controller.addMonthChangeListener( (year, month) { @@ -75,8 +71,13 @@ class _CustomStylePageState extends State { ], ), CalendarViewWidget( - calendarController: controller, - ), + calendarController: controller, + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }), ValueListenableBuilder( valueListenable: selectText, builder: (context, value, child) { diff --git a/example/lib/default_style_page.dart b/example/lib/default_style_page.dart index 39945b9..585be29 100644 --- a/example/lib/default_style_page.dart +++ b/example/lib/default_style_page.dart @@ -27,7 +27,7 @@ class _DefaultStylePageState extends State { minYearMonth: now.month - 5, maxYear: now.year, maxYearMonth: now.month + 5, - showMode: Constants.MODE_SHOW_MONTH_AND_WEEK); + showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK); controller.addMonthChangeListener( (year, month) { diff --git a/example/lib/main.dart b/example/lib/main.dart index 4bcbd68..7f579b1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,4 +1,5 @@ import 'package:example/only_week_page.dart'; +import 'package:example/red_style_page.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'blue_style_page.dart'; @@ -40,9 +41,8 @@ class MyApp extends StatelessWidget { "/only_week_view": (context) => OnlyWeekPage( title: "仅显示周视图", ), - "/blue_style_page":(context)=>BlueStylePage( - title:"蓝色背景Demo" - ) + "/blue_style_page": (context) => BlueStylePage(title: "蓝色背景Demo"), + "/red_style_page": (context) => RedStylePage(title: "蓝色背景Demo"), }, title: 'Flutter Demo', theme: ThemeData( @@ -95,9 +95,18 @@ class HomePage extends StatelessWidget { }, child: new Text("仅显示周视图"), ), - new RaisedButton(onPressed: (){ - Navigator.pushNamed(context, "/blue_style_page"); - },child: new Text("蓝色Demo"),) + new RaisedButton( + onPressed: () { + Navigator.pushNamed(context, "/blue_style_page"); + }, + child: new Text("蓝色Demo"), + ), + new RaisedButton( + onPressed: () { + Navigator.pushNamed(context, "/red_style_page"); + }, + child: new Text("红色Demo"), + ) ], ), ), diff --git a/example/lib/multi_select_style_page.dart b/example/lib/multi_select_style_page.dart index 332b9de..dfabfb1 100644 --- a/example/lib/multi_select_style_page.dart +++ b/example/lib/multi_select_style_page.dart @@ -22,17 +22,12 @@ class _MultiSelectStylePageState extends State { @override void initState() { controller = new CalendarController( - selectMode: Constants.MODE_MULTI_SELECT, - maxMultiSelectCount: 5, - minSelectYear: 2019, - minSelectMonth: 5, - minSelectDay: 20, - weekBarItemWidgetBuilder: () { - return CustomStyleWeekBarItem(); - }, - dayWidgetBuilder: (dateModel) { - return CustomStyleDayWidget(dateModel); - }); + selectMode: CalendarConstants.MODE_MULTI_SELECT, + maxMultiSelectCount: 5, + minSelectYear: 2019, + minSelectMonth: 5, + minSelectDay: 20, + ); controller.addMonthChangeListener( (year, month) { @@ -82,8 +77,13 @@ class _MultiSelectStylePageState extends State { ], ), CalendarViewWidget( - calendarController: controller, - ), + calendarController: controller, + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }), ValueListenableBuilder( valueListenable: selectText, builder: (context, value, child) { diff --git a/example/lib/only_week_page.dart b/example/lib/only_week_page.dart index 3a29296..c9af7d3 100644 --- a/example/lib/only_week_page.dart +++ b/example/lib/only_week_page.dart @@ -27,7 +27,7 @@ class _OnlyWeekPageState extends State { minYearMonth: now.month - 2, maxYear: now.year, maxYearMonth: now.month + 1, - showMode: Constants.MODE_SHOW_ONLY_WEEK); + showMode: CalendarConstants.MODE_SHOW_ONLY_WEEK); controller.addMonthChangeListener( (year, month) { diff --git a/example/lib/progress_style_page.dart b/example/lib/progress_style_page.dart index 39a5cf3..a36bd80 100644 --- a/example/lib/progress_style_page.dart +++ b/example/lib/progress_style_page.dart @@ -41,13 +41,8 @@ class _ProgressStylePageState extends State { }; controller = new CalendarController( - extraDataMap: progressMap, - weekBarItemWidgetBuilder: () { - return CustomStyleWeekBarItem(); - }, - dayWidgetBuilder: (dateModel) { - return ProgressStyleDayWidget(dateModel); - }); + extraDataMap: progressMap, + ); controller.addMonthChangeListener( (year, month) { @@ -97,8 +92,13 @@ class _ProgressStylePageState extends State { ], ), CalendarViewWidget( - calendarController: controller, - ), + calendarController: controller, + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return ProgressStyleDayWidget(dateModel); + }), ValueListenableBuilder( valueListenable: selectText, builder: (context, value, child) { diff --git a/example/lib/red_style_page.dart b/example/lib/red_style_page.dart new file mode 100644 index 0000000..a9f4501 --- /dev/null +++ b/example/lib/red_style_page.dart @@ -0,0 +1,236 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; + +class RedStylePage extends StatefulWidget { + RedStylePage({Key key, this.title}) : super(key: key); + + final String title; + + @override + _RedStylePageState createState() => _RedStylePageState(); +} + +class _RedStylePageState extends State { + ValueNotifier text; + ValueNotifier selectText; + + CalendarController controller; + + Map customExtraData = {}; + + Color pinkColor = Color(0xffFF8291); + + @override + void initState() { + controller = new CalendarController( + showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK, + extraDataMap: customExtraData); + + controller.addMonthChangeListener( + (year, month) { + text.value = "$year年$month月"; + }, + ); + + controller.addOnCalendarSelectListener((dateModel) { + //刷新选择的时间 + selectText.value = + "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"; + }); + + text = new ValueNotifier("${DateTime.now().year}年${DateTime.now().month}月"); + + selectText = new ValueNotifier( + "单选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); + } + + @override + Widget build(BuildContext context) { + var calendarWidget = CalendarViewWidget( + calendarController: controller, + margin: EdgeInsets.only(top: 20), + weekBarItemWidgetBuilder: () { + return CustomStyleWeekBarItem(); + }, + dayWidgetBuilder: (dateModel) { + return CustomStyleDayWidget(dateModel); + }, + ); + + return SafeArea( + child: Scaffold( + appBar: AppBar(), + body: new Container( + color: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 20), + child: new Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox( + height: 20, + ), + Stack( + alignment: Alignment.center, + children: [ + ValueListenableBuilder( + valueListenable: text, + builder: (context, value, child) { + return new Text( + "${text.value}", + style: TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.w700), + ); + }), + Positioned( + left: 0, + child: Icon( + Icons.notifications, + color: pinkColor, + ), + ), + Positioned( + right: 40, + child: Icon( + Icons.search, + color: pinkColor, + ), + ), + Positioned( + right: 0, + child: Icon( + Icons.add, + color: pinkColor, + ), + ), + ], + ), + calendarWidget, + ValueListenableBuilder( + valueListenable: selectText, + builder: (context, value, child) { + return Padding( + padding: const EdgeInsets.all(20.0), + child: new Text(selectText.value), + ); + }), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + controller.toggleExpandStatus(); + }, + tooltip: 'Increment', + child: Icon(Icons.add), + ), // This trailing comma makes auto-formatting nicer for build methods. + ), + ); + } +} + +class CustomStyleWeekBarItem extends BaseWeekBar { + List weekList = ["M", "T", "W", "T", "F", "S", "S"]; + + //可以直接重写build方法 + @override + Widget build(BuildContext context) { + List children = List(); + + var items = getWeekDayWidget(); + children.add(Row( + children: items, + )); + children.add(Divider( + color: Colors.grey, + )); + return Column( + children: children, + ); + } + + @override + Widget getWeekBarItem(int index) { + return new Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: new Center( + child: new Text( + weekList[index], + style: + TextStyle(fontWeight: FontWeight.w700, color: Color(0xffBBC0C6)), + ), + ), + ); + } +} + +class CustomStyleDayWidget extends BaseCombineDayWidget { + CustomStyleDayWidget(DateModel dateModel) : super(dateModel); + + TextStyle normalTextStyle = + TextStyle(fontWeight: FontWeight.w700, color: Colors.black); + + TextStyle noIsCurrentMonthTextStyle = + TextStyle(fontWeight: FontWeight.w700, color: Colors.grey); + + @override + Widget getNormalWidget(DateModel dateModel) { + return Container( + margin: EdgeInsets.all(8), + child: new Stack( + alignment: Alignment.center, + children: [ + new Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + //公历 + new Expanded( + child: Center( + child: new Text( + dateModel.day.toString(), + style: dateModel.isCurrentMonth + ? normalTextStyle + : noIsCurrentMonthTextStyle, + ), + ), + ), + ], + ), + ], + ), + ); + } + + @override + Widget getSelectedWidget(DateModel dateModel) { + return Container( +// margin: EdgeInsets.all(8), + decoration: new BoxDecoration( + shape: BoxShape.circle, + color: Color(0xffFF8291), + ), + child: new Stack( + alignment: Alignment.center, + children: [ + new Column( + mainAxisSize: MainAxisSize.max, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + //公历 + new Expanded( + child: Center( + child: new Text( + dateModel.day.toString(), + style: TextStyle(color: Colors.white), + ), + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/calendar_provider.dart b/lib/calendar_provider.dart index 846e4a1..a4db0c1 100644 --- a/lib/calendar_provider.dart +++ b/lib/calendar_provider.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/cache_data.dart'; import 'package:flutter_custom_calendar/configuration.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/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart'; @@ -110,6 +111,10 @@ class CalendarProvider extends ChangeNotifier { CalendarConfiguration calendarConfiguration, EdgeInsetsGeometry padding, EdgeInsetsGeometry margin, + double itemSize, + double verticalSpacing, + DayWidgetBuilder dayWidgetBuilder, + WeekBarItemWidgetBuilder weekBarItemWidgetBuilder, }) { LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider initData"); if (selectedDateList != null) { @@ -119,14 +124,21 @@ class CalendarProvider extends ChangeNotifier { this.calendarConfiguration = calendarConfiguration; this.calendarConfiguration.padding = padding; this.calendarConfiguration.margin = margin; + this.calendarConfiguration.itemSize = itemSize; + this.calendarConfiguration.verticalSpacing = verticalSpacing; + this.calendarConfiguration.dayWidgetBuilder=dayWidgetBuilder; + this.calendarConfiguration.weekBarItemWidgetBuilder=weekBarItemWidgetBuilder; + //lastClickDateModel,默认是选中的item,如果为空的话,默认是当前的时间 this.lastClickDateModel = selectDateModel != null ? selectDateModel : DateModel.fromDateTime(DateTime.now()) ..day = 15; //初始化展示状态 - if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK || - calendarConfiguration.showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) { + if (calendarConfiguration.showMode == + CalendarConstants.MODE_SHOW_ONLY_WEEK || + calendarConfiguration.showMode == + CalendarConstants.MODE_SHOW_WEEK_AND_MONTH) { expandStatus = ValueNotifier(false); } else { expandStatus = ValueNotifier(true); @@ -151,8 +163,10 @@ class CalendarProvider extends ChangeNotifier { } //如果第一个页面展示的是月视图,需要计算下初始化的高度 - if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_MONTH || - calendarConfiguration.showMode == Constants.MODE_SHOW_MONTH_AND_WEEK) { + if (calendarConfiguration.showMode == + CalendarConstants.MODE_SHOW_ONLY_MONTH || + calendarConfiguration.showMode == + CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) { int lineCount = DateUtil.getMonthViewLineCount( calendarConfiguration.nowYear, calendarConfiguration.nowMonth); totalHeight = calendarConfiguration.itemSize * (lineCount) + diff --git a/lib/configuration.dart b/lib/configuration.dart index 798c3cd..2047d50 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -41,9 +41,9 @@ class CalendarConfiguration { /** * UI绘制方面的绘制 */ + double itemSize; //默认是屏幕宽度/7 double verticalSpacing; //日历item之间的竖直方向间距,默认10 BoxDecoration boxDecoration; //整体的背景设置 - double itemSize; //默认是屏幕宽度/7 EdgeInsetsGeometry padding; EdgeInsetsGeometry margin; diff --git a/lib/constants/constants.dart b/lib/constants/constants.dart index c87b3ac..2917567 100644 --- a/lib/constants/constants.dart +++ b/lib/constants/constants.dart @@ -1,4 +1,4 @@ -class Constants { +class CalendarConstants { //单选或者多选模式 static const int MODE_SINGLE_SELECT = 1; diff --git a/lib/controller.dart b/lib/controller.dart index d131673..c52c276 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -31,10 +31,8 @@ class CalendarController { PageController weekController; //星期的controller CalendarController( - {int selectMode = Constants.MODE_SINGLE_SELECT, - int showMode = Constants.MODE_SHOW_ONLY_MONTH, - DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget, - WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget, + {int selectMode = CalendarConstants.MODE_SINGLE_SELECT, + int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH, int minYear = 1971, int maxYear = 2055, int minYearMonth = 1, @@ -50,8 +48,6 @@ class CalendarController { Set selectedDateTimeList = EMPTY_SET, DateModel selectDateModel, int maxMultiSelectCount = 9999, - double verticalSpacing = 10, - double itemSize, Map extraDataMap = EMPTY_MAP}) { LogUtil.log(TAG: this.runtimeType, message: "init CalendarConfiguration"); //如果没有指定当前月份和年份,默认是当年时间 @@ -62,26 +58,22 @@ 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, - verticalSpacing: verticalSpacing, - itemSize: itemSize); - - calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder; - calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder; + 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 @@ -100,7 +92,7 @@ class CalendarController { maxYearMonth, ))}"); - if (showMode != Constants.MODE_SHOW_ONLY_WEEK) { + if (showMode != CalendarConstants.MODE_SHOW_ONLY_WEEK) { //初始化pageController,initialPage默认是当前时间对于的页面 int initialPage = 0; int nowMonthIndex = 0; @@ -138,7 +130,7 @@ class CalendarController { "初始化月份视图的信息:一共有${monthList.length}个月,initialPage为${nowMonthIndex}"); } - if (showMode != Constants.MODE_SHOW_ONLY_MONTH) { + if (showMode != CalendarConstants.MODE_SHOW_ONLY_MONTH) { //计算一共多少周 //计算方法:第一天是周几,最后一天是周几,中间的天数/7后加上2就是结果了 int initialWeekPage = 0; @@ -182,8 +174,6 @@ class CalendarController { calendarConfiguration.weekList = weekList; calendarConfiguration.monthController = monthController; calendarConfiguration.weekController = weekController; - calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder; - calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder; } //月份切换监听 diff --git a/lib/utils/lunar_util.dart b/lib/utils/lunar_util.dart index 23b0755..ce18e9a 100644 --- a/lib/utils/lunar_util.dart +++ b/lib/utils/lunar_util.dart @@ -908,7 +908,7 @@ class LunarUtil { if (day == 1) { return numToChineseMonth(month, leap); } - return Constants.LUNAR_DAY_TEXT[day - 1]; + return CalendarConstants.LUNAR_DAY_TEXT[day - 1]; } /** @@ -920,9 +920,9 @@ class LunarUtil { */ static String numToChineseMonth(int month, int leap) { if (leap == 1) { - return "闰" + Constants.LUNAR_MONTH_TEXT[month - 1]; + return "闰" + CalendarConstants.LUNAR_MONTH_TEXT[month - 1]; } - return Constants.LUNAR_MONTH_TEXT[month - 1]; + return CalendarConstants.LUNAR_MONTH_TEXT[month - 1]; } static String getString(int month, int day) { diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index f5d6c7b..d8b1871 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/calendar_provider.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/LogUtil.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/widget/month_view_pager.dart'; @@ -23,15 +22,28 @@ class CalendarViewWidget extends StatefulWidget { EdgeInsetsGeometry padding; EdgeInsetsGeometry margin; + //默认是屏幕宽度/7 + double itemSize; + + //日历item之间的竖直方向间距,默认10 + double verticalSpacing; + + DayWidgetBuilder dayWidgetBuilder; + WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; + //控制器 final CalendarController calendarController; CalendarViewWidget( {Key key, + this.dayWidgetBuilder = defaultCustomDayWidget, + this.weekBarItemWidgetBuilder = defaultWeekBarWidget, @required this.calendarController, this.boxDecoration, this.padding = EdgeInsets.zero, - this.margin = EdgeInsets.zero}) + this.margin = EdgeInsets.zero, + this.verticalSpacing = 10, + this.itemSize}) : super(key: key); @override @@ -45,7 +57,11 @@ class _CalendarViewWidgetState extends State { widget.calendarController.calendarProvider.initData( calendarConfiguration: widget.calendarController.calendarConfiguration, padding: widget.padding, - margin: widget.margin); + margin: widget.margin, + itemSize: widget.itemSize, + verticalSpacing: widget.verticalSpacing, + dayWidgetBuilder: widget.dayWidgetBuilder, + weekBarItemWidgetBuilder: widget.weekBarItemWidgetBuilder); super.initState(); } @@ -99,15 +115,15 @@ class CalendarContainerState extends State expand = calendarProvider.expandStatus.value; if (calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_ONLY_WEEK) { + CalendarConstants.MODE_SHOW_ONLY_WEEK) { widgets.add(const WeekViewPager()); } else if (calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_WEEK_AND_MONTH) { + CalendarConstants.MODE_SHOW_WEEK_AND_MONTH) { widgets.add(const MonthViewPager()); widgets.add(const WeekViewPager()); index = 1; } else if (calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_MONTH_AND_WEEK) { + CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) { widgets.add(const MonthViewPager()); widgets.add(const WeekViewPager()); index = 0; @@ -119,9 +135,9 @@ class CalendarContainerState extends State //如果需要视图切换的话,才需要添加监听,不然不需要监听变化 if (calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_WEEK_AND_MONTH || + CalendarConstants.MODE_SHOW_WEEK_AND_MONTH || calendarProvider.calendarConfiguration.showMode == - Constants.MODE_SHOW_MONTH_AND_WEEK) { + CalendarConstants.MODE_SHOW_MONTH_AND_WEEK) { calendarProvider.expandStatus.addListener(() { setState(() { print( @@ -147,7 +163,7 @@ class CalendarContainerState extends State widget.calendarController.addMonthChangeListener((year, month) { if (widget.calendarController.calendarProvider.calendarConfiguration .showMode != - Constants.MODE_SHOW_ONLY_WEEK) { + CalendarConstants.MODE_SHOW_ONLY_WEEK) { //月份切换的时候,如果高度发生变化的话,需要setState使高度整体自适应 int lineCount = DateUtil.getMonthViewLineCount(year, month); double newHeight = itemHeight * (lineCount) + diff --git a/lib/widget/default_week_bar.dart b/lib/widget/default_week_bar.dart index 1961586..0b8935e 100644 --- a/lib/widget/default_week_bar.dart +++ b/lib/widget/default_week_bar.dart @@ -47,7 +47,7 @@ class DefaultWeekBar extends BaseWeekBar { height: 40, alignment: Alignment.center, child: new Text( - Constants.WEEK_LIST[index], + CalendarConstants.WEEK_LIST[index], style: topWeekTextStyle, ), ); diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 6b3a8d5..9c02b49 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -125,7 +125,7 @@ class _MonthViewState extends State itemBuilder: (context, index) { DateModel dateModel = items[index]; //判断是否被选择 - if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { + if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) { if (calendarProvider.selectedDateList.contains(dateModel)) { dateModel.isSelected = true; } else { @@ -213,7 +213,7 @@ class ItemContainerState extends State { //范围外不可点击 if (!dateModel.isInRange) { //多选回调 - if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { + if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) { configuration.multiSelectOutOfRange(); } return; @@ -221,7 +221,7 @@ class ItemContainerState extends State { calendarProvider.lastClickDateModel = dateModel; - if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { + if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) { //多选,判断是否超过限制,超过范围 if (calendarProvider.selectedDateList.length == configuration.maxMultiSelectCount) { diff --git a/lib/widget/week_view.dart b/lib/widget/week_view.dart index c71bb6f..7542ffc 100644 --- a/lib/widget/week_view.dart +++ b/lib/widget/week_view.dart @@ -72,7 +72,7 @@ class _WeekViewState extends State { itemBuilder: (context, index) { DateModel dateModel = items[index]; //判断是否被选择 - if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { + if (configuration.selectMode == CalendarConstants.MODE_MULTI_SELECT) { if (calendarProvider.selectedDateList.contains(dateModel)) { dateModel.isSelected = true; } else { From c2308a96fc9c7870831db3786c153e89a6fdbd8b Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 18:01:00 +0800 Subject: [PATCH 11/25] =?UTF-8?q?readme=E6=96=87=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README_en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_en.md b/README_en.md index 638ddf0..4836c2f 100644 --- a/README_en.md +++ b/README_en.md @@ -5,7 +5,7 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 A calendar widget in flutter,you can design what you want to show! -### Language: 中文简体|[English](https://lxd312569496.github.io/flutter_custom_calendar/) +### Language:English|[中文简体](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/README.md) * Overview * Online Demo From aa43c858b1397e32c8841bc1770811db82833c83 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 18:11:12 +0800 Subject: [PATCH 12/25] =?UTF-8?q?readme=E6=96=87=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 +++++++++++++++++++++++++++++++++- README_en.md | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 020a83d..f65fc23 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,47 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 ### 效果图 + + + + + + + + + + + + + + + + + + + + + +
+ - + +
+ + +
+ + + + +
## 使用 diff --git a/README_en.md b/README_en.md index 4836c2f..005e48c 100644 --- a/README_en.md +++ b/README_en.md @@ -35,15 +35,47 @@ Calendar supports web Preview:[Click here for preview](https://lxd312569496.gi ### Example + + + + + + + + + + + + + + + + + + + + + +
+ - + +
+ + +
+ + + + +
## Getting Started From a2ae0ce266fdb9229b2f5a47ffd96b248d635a76 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Thu, 31 Oct 2019 18:17:04 +0800 Subject: [PATCH 13/25] =?UTF-8?q?readme=E6=96=87=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +---- README_en.md | 6 ++---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index f65fc23..c5c2bbc 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,7 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 - - - - + diff --git a/README_en.md b/README_en.md index 005e48c..11b4324 100644 --- a/README_en.md +++ b/README_en.md @@ -40,11 +40,9 @@ Calendar supports web Preview:[Click here for preview](https://lxd312569496.gi - - - - + + From 70a5863d8bdf8263a10e94ebeaef003ae49f90c5 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 18:21:56 +0800 Subject: [PATCH 14/25] =?UTF-8?q?readme=E6=96=87=E6=A1=A3=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87=E8=AF=B4?= =?UTF-8?q?=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README_en.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README_en.md b/README_en.md index 11b4324..55cedaa 100644 --- a/README_en.md +++ b/README_en.md @@ -1,7 +1,6 @@ ## FlutterCalendarWidget -Flutter上的一个日历控件,可以定制成自己想要的样子。 A calendar widget in flutter,you can design what you want to show! From 39a76a3154aa0dcf9e34596814c879683ef279af Mon Sep 17 00:00:00 2001 From: zmtzawqlp Date: Thu, 31 Oct 2019 18:45:10 +0800 Subject: [PATCH 15/25] format readme --- API.md | 173 ++++++++++++++++++++++++++++----------------------- README.md | 21 +++---- README_en.md | 21 +++---- 3 files changed, 114 insertions(+), 101 deletions(-) diff --git a/API.md b/API.md index 4c2cd88..e5e0185 100644 --- a/API.md +++ b/API.md @@ -1,6 +1,23 @@ ## 主要Api文档 +- [主要Api文档](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3) + - [配置日历的UI](#%e9%85%8d%e7%bd%ae%e6%97%a5%e5%8e%86%e7%9a%84ui) + - [参数说明](#%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e) + - [配置Controller](#%e9%85%8d%e7%bd%aecontroller) + - [通用参数说明](#%e9%80%9a%e7%94%a8%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e) + - [给controller添加事件监听](#%e7%bb%99controller%e6%b7%bb%e5%8a%a0%e4%ba%8b%e4%bb%b6%e7%9b%91%e5%90%ac) + - [利用controller来控制日历的切换,支持配置动画](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e6%8e%a7%e5%88%b6%e6%97%a5%e5%8e%86%e7%9a%84%e5%88%87%e6%8d%a2%e6%94%af%e6%8c%81%e9%85%8d%e7%bd%ae%e5%8a%a8%e7%94%bb) + - [利用controller来获取当前日历的状态和数据](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e8%8e%b7%e5%8f%96%e5%bd%93%e5%89%8d%e6%97%a5%e5%8e%86%e7%9a%84%e7%8a%b6%e6%80%81%e5%92%8c%e6%95%b0%e6%8d%ae) + - [如何自定义UI](#%e5%a6%82%e4%bd%95%e8%87%aa%e5%ae%9a%e4%b9%89ui) + - [自定义WeekBar](#%e8%87%aa%e5%ae%9a%e4%b9%89weekbar) + - [自定义日历Item:](#%e8%87%aa%e5%ae%9a%e4%b9%89%e6%97%a5%e5%8e%86item) + - [根据实际场景,自定义额外的数据extraData](#%e6%a0%b9%e6%8d%ae%e5%ae%9e%e9%99%85%e5%9c%ba%e6%99%af%e8%87%aa%e5%ae%9a%e4%b9%89%e9%a2%9d%e5%a4%96%e7%9a%84%e6%95%b0%e6%8d%aeextradata) + - [实现进度条样式的日历](#%e5%ae%9e%e7%8e%b0%e8%bf%9b%e5%ba%a6%e6%9d%a1%e6%a0%b7%e5%bc%8f%e7%9a%84%e6%97%a5%e5%8e%86) + - [实现自定义各种标记的日历](#%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%ae%9a%e4%b9%89%e5%90%84%e7%a7%8d%e6%a0%87%e8%ae%b0%e7%9a%84%e6%97%a5%e5%8e%86) + - [手动修改自定义的数据](#%e6%89%8b%e5%8a%a8%e4%bf%ae%e6%94%b9%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9a%84%e6%95%b0%e6%8d%ae) + - [DateModel实体类](#datemodel%e5%ae%9e%e4%bd%93%e7%b1%bb) + ### 配置日历的UI 日历UI相关的配置是在CalendarViewWidget的构造函数里面进行配置就行了。 @@ -19,15 +36,15 @@ ``` #### 参数说明 -属性 | 含义 | 默认值 -:-: | :-: | :-: -weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 -dayWidgetBuilder | 创建日历item | 默认样式 -verticalSpacing|日历item之间的竖直方向间距|默认10 -boxDecoration |整体的背景设置|默认为空 -itemSize| 每个item的边长|手机默认是屏幕宽度/7,网页默认屏幕高度/7| -padding|日历的padding |默认为EdgeInsets.zero -margin| 日历的padding|默认为EdgeInsets.zero +| 属性 | 含义 | 默认值 | +| :----------------------: | :------------------------: | :--------------------------------------: | +| weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 | +| dayWidgetBuilder | 创建日历item | 默认样式 | +| verticalSpacing | 日历item之间的竖直方向间距 | 默认10 | +| boxDecoration | 整体的背景设置 | 默认为空 | +| itemSize | 每个item的边长 | 手机默认是屏幕宽度/7,网页默认屏幕高度/7 | +| padding | 日历的padding | 默认为EdgeInsets.zero | +| margin | 日历的padding | 默认为EdgeInsets.zero | @@ -62,60 +79,60 @@ margin| 日历的padding|默认为EdgeInsets.zero #### 通用参数说明 -属性 | 含义 | 默认值 -:-: | :-: | :-: -selectMode | 选择模式,表示单选或者多选 | 默认是单选
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2; -showMode|展示模式| 默认是只展示月视图
static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图
static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图
static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图
static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 -minYear | 日历显示的最小年份| 1971 -maxYear | 日历显示的最大年份| 2055 -minYearMonth | 日历显示的最小年份的月份| 1 -maxYearMonth | 日历显示的最大年份的月份| 12 -nowYear | 日历显示的当前的年份| -1 -nowMonth | 日历显示的当前的月份| -1 -minSelectYear | 可以选择的最小年份| 1971 -minSelectMonth | 可以选择的最小年份的月份| 1 -minSelectDay | 可以选择的最小月份的日子| 1 -maxSelectYear | 可以选择的最大年份| 2055 -maxSelectMonth | 可以选择的最大年份的月份| 12 -maxSelectDay | 可以选择的最大月份的日子| 30,注意:不能超过对应月份的总天数 -selectedDateList | 被选中的日期,用于多选| 默认为空Set, Set selectedDateList = new Set() -selectDateModel | 当前选择项,用于单选| 默认为空 -maxMultiSelectCount | 多选,最多选多少个| hhh -extraDataMap | 自定义额外的数据| 默认为空Map,Map extraDataMap = new Map() +| 属性 | 含义 | 默认值 | +| :-----------------: | :-----------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| selectMode | 选择模式,表示单选或者多选 | 默认是单选
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2; | +| showMode | 展示模式 | 默认是只展示月视图
static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图
static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图
static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图
static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 | +| minYear | 日历显示的最小年份 | 1971 | +| maxYear | 日历显示的最大年份 | 2055 | +| minYearMonth | 日历显示的最小年份的月份 | 1 | +| maxYearMonth | 日历显示的最大年份的月份 | 12 | +| nowYear | 日历显示的当前的年份 | -1 | +| nowMonth | 日历显示的当前的月份 | -1 | +| minSelectYear | 可以选择的最小年份 | 1971 | +| minSelectMonth | 可以选择的最小年份的月份 | 1 | +| minSelectDay | 可以选择的最小月份的日子 | 1 | +| maxSelectYear | 可以选择的最大年份 | 2055 | +| maxSelectMonth | 可以选择的最大年份的月份 | 12 | +| maxSelectDay | 可以选择的最大月份的日子 | 30,注意:不能超过对应月份的总天数 | +| selectedDateList | 被选中的日期,用于多选 | 默认为空Set, Set selectedDateList = new Set() | +| selectDateModel | 当前选择项,用于单选 | 默认为空 | +| maxMultiSelectCount | 多选,最多选多少个 | hhh | +| extraDataMap | 自定义额外的数据 | 默认为空Map,Map extraDataMap = new Map() | #### 给controller添加事件监听 -方法 | 含义 | 默认值 -:-: | :-: | :-: -void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 | -void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 | -void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 | -void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 | -void addExpandChangeListener(ValueChanged expandChange)|监听日历的展开收缩状态| +| 方法 | 含义 | 默认值 | +| :-----------------------------------------------------------------------: | :--------------------: | :----: | +| void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 | +| void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 | +| void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 | +| void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 | +| void addExpandChangeListener(ValueChanged expandChange) | 监听日历的展开收缩状态 | #### 利用controller来控制日历的切换,支持配置动画 -方法 | 含义 | 默认值 -:-: | :-: | :-: -Future previousPage()|滑动到上一个页面,会自动根据当前的展开状态,滑动到上一个月或者上一个星期。如果已经在第一个页面,没有上一个页面,就会返回false,其他情况返回true| -Future nextPage()|滑动到下一个页面,会自动根据当前的展开状态,滑动到下一个月或者下一个星期。如果已经在最后一个页面,没有下一个页面,就会返回false,其他情况返回true| -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()|切换到上一个月份| -void toggleExpandStatus()|切换展开状态| -void changeExtraData(Map newMap)|修改自定义的额外数据并刷新日历| +| 方法 | 含义 | 默认值 | +| :-------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----: | +| Future previousPage() | 滑动到上一个页面,会自动根据当前的展开状态,滑动到上一个月或者上一个星期。如果已经在第一个页面,没有上一个页面,就会返回false,其他情况返回true | +| Future nextPage() | 滑动到下一个页面,会自动根据当前的展开状态,滑动到下一个月或者下一个星期。如果已经在最后一个页面,没有下一个页面,就会返回false,其他情况返回true | +| 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() | 切换到上一个月份 | +| void toggleExpandStatus() | 切换展开状态 | +| void changeExtraData(Map newMap) | 修改自定义的额外数据并刷新日历 | #### 利用controller来获取当前日历的状态和数据 -方法 | 含义 | 默认值 -:-: | :-: | :-: -DateTime getCurrentMonth()|获取当前的月份| -Set getMultiSelectCalendar()|获取被选中的日期,多选| -DateModel getSingleSelectCalendar()|获取被选中的日期,单选| +| 方法 | 含义 | 默认值 | +| :-------------------------------------: | :--------------------: | :----: | +| DateTime getCurrentMonth() | 获取当前的月份 | +| Set getMultiSelectCalendar() | 获取被选中的日期,多选 | +| DateModel getSingleSelectCalendar() | 获取被选中的日期,单选 | @@ -290,29 +307,29 @@ class DefaultCustomDayWidget extends BaseCustomDayWidget { ### DateModel实体类 日历所用的日期的实体类DateModel,有下面这些属性。可以在自定义绘制DayWidget的时候,根据相应的属性,进行判断后,绘制相应的UI。 -属性|含义|类型|默认值 -:-: | :-: | :-: |:-: -year|年份|int| -month|月份|int| -day|日期|int|默认为1 -lunarYear|农历年份|int| -lunarMonth|农历月份|int| -lunarDay|农历日期|int| -lunarString|农历字符串|String| -solarTerm|24节气|String| -gregorianFestival|gregorianFestival|String| -traditionFestival|传统农历节日|String| -isCurrentDay|是否是今天|bool|false -isLeapYear|是否是闰年|bool|false -isWeekend|是否是周末|bool|false -isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false -isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false -extraData|自定义的额外数据|Object|默认为空 -isCurrentMonth|是否是当前月份|bool| - - -方法|含义| -:-: | :-: | -DateTime getDateTime()|将DateModel转化成DateTime -DateModel fromDateTime(DateTime dateTime)|根据DateTime创建对应的model,并初始化农历和传统节日等信息 -bool operator ==(Object other)|重写==方法,可以判断两个dateModel是否是同一天 \ No newline at end of file +| 属性 | 含义 | 类型 | 默认值 | +| :---------------: | :---------------------------------------------------: | :----: | :------: | +| year | 年份 | int | +| month | 月份 | int | +| day | 日期 | int | 默认为1 | +| lunarYear | 农历年份 | int | +| lunarMonth | 农历月份 | int | +| lunarDay | 农历日期 | int | +| lunarString | 农历字符串 | String | +| solarTerm | 24节气 | String | +| gregorianFestival | gregorianFestival | String | +| traditionFestival | 传统农历节日 | String | +| isCurrentDay | 是否是今天 | bool | false | +| isLeapYear | 是否是闰年 | bool | false | +| isWeekend | 是否是周末 | bool | false | +| isInRange | 是否在范围内,比如可以实现在某个范围外,设置置灰的功能 | bool | false | +| isSelected | 是否被选中,用来实现一些标记或者选择功能 | bool | false | +| extraData | 自定义的额外数据 | Object | 默认为空 | +| isCurrentMonth | 是否是当前月份 | bool | + + +| 方法 | 含义 | +| :---------------------------------------: | :-------------------------------------------------------: | +| DateTime getDateTime() | 将DateModel转化成DateTime | +| DateModel fromDateTime(DateTime dateTime) | 根据DateTime创建对应的model,并初始化农历和传统节日等信息 | +| bool operator ==(Object other) | 重写==方法,可以判断两个dateModel是否是同一天 | \ No newline at end of file diff --git a/README.md b/README.md index c5c2bbc..522de37 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,16 @@ Flutter上的一个日历控件,可以定制成自己想要的样子。 -### Language: [English](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/README_en.md)|中文简体 - -* 概述 -* 在线Demo -* 效果图 -* 快速使用 -* 2.0版本 -* 注意事项 -* 主要Api文档 - - +Language: [English](README_en.md)|中文简体 + +- [FlutterCalendarWidget](#fluttercalendarwidget) + - [概述](#%e6%a6%82%e8%bf%b0) + - [在线Demo](#%e5%9c%a8%e7%ba%bfdemo) + - [效果图](#%e6%95%88%e6%9e%9c%e5%9b%be) +- [使用](#%e4%bd%bf%e7%94%a8) +- [2.0版本](#20%e7%89%88%e6%9c%ac) +- [注意事项](#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9) +- [主要API文档](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3) ### 概述 diff --git a/README_en.md b/README_en.md index 11b4324..e6ffc60 100644 --- a/README_en.md +++ b/README_en.md @@ -1,21 +1,18 @@ ## FlutterCalendarWidget -Flutter上的一个日历控件,可以定制成自己想要的样子。 A calendar widget in flutter,you can design what you want to show! +Language:English|[中文简体](README.md) -### Language:English|[中文简体](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/README.md) - -* Overview -* Online Demo -* Example -* Getting Started -* 2.0 version -* matters needing attention -* API Documentation - - +- [FlutterCalendarWidget](#fluttercalendarwidget) + - [Overview](#overview) + - [Online Demo](#online-demo) + - [Example](#example) +- [Getting Started](#getting-started) +- [2.0 version](#20-version) +- [matters needing attention](#matters-needing-attention) +- [API Documentation](#api-documentation) ### Overview From 42a21fc4b3085823a194ade2a0bb3f7e7cc6b7d5 Mon Sep 17 00:00:00 2001 From: zmtzawqlp Date: Thu, 31 Oct 2019 18:50:01 +0800 Subject: [PATCH 16/25] format readme --- README.md | 2 +- README_en.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 522de37..06586a6 100644 --- a/README.md +++ b/README.md @@ -134,5 +134,5 @@ controller.nextPage();//操作日历切换到下一页 ## 主要API文档 -[API Documentation](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/API.md) +[API Documentation](API.md) diff --git a/README_en.md b/README_en.md index e6ffc60..30d64f3 100644 --- a/README_en.md +++ b/README_en.md @@ -135,6 +135,6 @@ Major changes: ## API Documentation -[API Documentation](https://github.com/fluttercandies/flutter_custom_calendar/blob/master/API.md) +[API Documentation](API.md) From 8879b04fa72f078e130adcbf94d1fd4efc27b652 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 19:53:28 +0800 Subject: [PATCH 17/25] =?UTF-8?q?fix=20bug=EF=BC=9A=E4=BC=A0=E7=BB=9F?= =?UTF-8?q?=E8=8A=82=E6=97=A5=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/model/date_model.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/model/date_model.dart b/lib/model/date_model.dart index 0882e3b..d0ae60d 100644 --- a/lib/model/date_model.dart +++ b/lib/model/date_model.dart @@ -45,7 +45,7 @@ class DateModel { //传统农历节日 String get traditionFestival => - LunarUtil.getTraditionFestival(year, month, day); + LunarUtil.getTraditionFestival(lunarYear, lunarMonth, lunarDay); bool isCurrentMonth; //是否是当前月份 From fdcb1c2c8508f3327131d22085008fc2c52511ef Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Thu, 31 Oct 2019 22:03:19 +0800 Subject: [PATCH 18/25] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=8C=E5=88=A0=E6=8E=89=E6=B2=A1=E7=94=A8?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/lib/blue_style_page.dart | 12 ++--- example/lib/custom_sign_page.dart | 3 +- example/lib/custom_style_page.dart | 3 +- example/lib/default_style_page.dart | 9 ++-- example/lib/main.dart | 63 +----------------------- example/lib/multi_select_style_page.dart | 4 +- example/lib/only_week_page.dart | 1 + example/lib/progress_style_page.dart | 3 +- example/lib/red_style_page.dart | 11 +++-- lib/utils/date_util.dart | 3 -- lib/widget/base_day_view.dart | 2 +- lib/widget/calendar_view.dart | 15 +++--- lib/widget/fast_click_widget.dart | 32 ------------ lib/widget/month_view.dart | 2 - lib/widget/month_view_pager.dart | 3 +- lib/widget/week_view.dart | 1 - lib/widget/week_view_pager.dart | 7 +-- 17 files changed, 41 insertions(+), 133 deletions(-) delete mode 100644 lib/widget/fast_click_widget.dart diff --git a/example/lib/blue_style_page.dart b/example/lib/blue_style_page.dart index 297c2f0..121704d 100644 --- a/example/lib/blue_style_page.dart +++ b/example/lib/blue_style_page.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/flutter_custom_calendar.dart'; -import 'package:flutter_custom_calendar/style/style.dart'; -import 'package:random_pk/random_pk.dart'; class BlueStylePage extends StatefulWidget { @@ -23,6 +21,7 @@ class _BlueStylePageState extends State { @override void initState() { + super.initState(); controller = new CalendarController( showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK, @@ -81,8 +80,7 @@ class _BlueStylePageState extends State { height: 20, ), Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - mainAxisSize: MainAxisSize.min, + mainAxisSize: MainAxisSize.max, children: [ Container( height: 100, @@ -146,7 +144,7 @@ class _BlueStylePageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"]; + final List weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"]; //可以直接重写build方法 @override @@ -183,10 +181,10 @@ class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleDayWidget extends BaseCombineDayWidget { CustomStyleDayWidget(DateModel dateModel) : super(dateModel); - TextStyle normalTextStyle = + final TextStyle normalTextStyle = TextStyle(fontWeight: FontWeight.w700, color: Colors.black); - TextStyle noIsCurrentMonthTextStyle = + final TextStyle noIsCurrentMonthTextStyle = TextStyle(fontWeight: FontWeight.w700, color: Colors.grey); @override diff --git a/example/lib/custom_sign_page.dart b/example/lib/custom_sign_page.dart index b4df94c..63466f9 100644 --- a/example/lib/custom_sign_page.dart +++ b/example/lib/custom_sign_page.dart @@ -43,6 +43,7 @@ class _CustomSignPageState extends State { @override void initState() { + super.initState(); controller = new CalendarController( extraDataMap: customExtraData); @@ -124,7 +125,7 @@ class _CustomSignPageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["一", "二", "三", "四", "五", "六", "日"]; + final List weekList = ["一", "二", "三", "四", "五", "六", "日"]; @override Widget getWeekBarItem(int index) { diff --git a/example/lib/custom_style_page.dart b/example/lib/custom_style_page.dart index 6f587ca..3aec4c9 100644 --- a/example/lib/custom_style_page.dart +++ b/example/lib/custom_style_page.dart @@ -21,6 +21,7 @@ class _CustomStylePageState extends State { @override void initState() { + super.initState(); controller = new CalendarController(); controller.addMonthChangeListener( @@ -96,7 +97,7 @@ class _CustomStylePageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["一", "二", "三", "四", "五", "六", "日"]; + final List weekList = ["一", "二", "三", "四", "五", "六", "日"]; @override Widget getWeekBarItem(int index) { diff --git a/example/lib/default_style_page.dart b/example/lib/default_style_page.dart index 585be29..bb20ddd 100644 --- a/example/lib/default_style_page.dart +++ b/example/lib/default_style_page.dart @@ -21,12 +21,13 @@ class _DefaultStylePageState extends State { @override void initState() { + super.initState(); DateTime now = DateTime.now(); controller = new CalendarController( - minYear: now.year, - minYearMonth: now.month - 5, - maxYear: now.year, - maxYearMonth: now.month + 5, + minYear: now.year-1, + minYearMonth: 1, + maxYear: now.year+1, + maxYearMonth: 12, showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK); controller.addMonthChangeListener( diff --git a/example/lib/main.dart b/example/lib/main.dart index 7f579b1..3258a09 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,7 @@ import 'package:example/only_week_page.dart'; import 'package:example/red_style_page.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/rendering.dart'; + import 'blue_style_page.dart'; import 'custom_sign_page.dart'; import 'custom_style_page.dart'; @@ -114,64 +114,3 @@ class HomePage extends StatelessWidget { } } -// -//# Desktop Flutter Example -// -//This is the standard Flutter template application, modified to run on desktop. -// -//The `linux` and `windows` directories serve as early prototypes of -//what will eventually become the `flutter create` templates for desktop, and will -//be evolving over time to better reflect that goal. The `macos` directory has -//now become a `flutter create` template, so is largely identical to what that -//command creates. -// -//## Building and Running -// -//See [the main project README](../README.md). -// -//To build without running, use `flutter build macos`/`windows`/`linux` rather than `flutter run`, as with -//a standard Flutter project. -// -//## Dart Differences from Flutter Template -// -//The `main.dart` and `pubspec.yaml` have minor changes to support desktop: -//* `debugDefaultTargetPlatformOverride` is set to avoid 'Unknown platform' -//exceptions. -//* The font is explicitly set to Roboto, and Roboto is bundled via -//`pubspec.yaml`, to ensure that text displays on all platforms. -// -//See the [Flutter Application Requirements section of the Flutter page on -//desktop support](https://github.com/flutter/flutter/wiki/Desktop-shells#flutter-application-requirements) -//for more information. -// -//## Adapting for Another Project -// -//Since `flutter create` is not yet supported for Windows and Linux, the easiest -//way to try out desktop support with an existing Flutter application on those -//platforms is to copy the platform directories from this example; see below for -//details. For macOS, just run `flutter create --macos .` in your project. -// -//Be sure to read the [Flutter page on desktop -//support](https://github.com/flutter/flutter/wiki/Desktop-shells) before trying to -//run an existing project on desktop, especially the [Flutter Application Requirements -//section](https://github.com/flutter/flutter/wiki/Desktop-shells#flutter-application-requirements). -// -//### Coping the Desktop Runners -// -//The 'linux' and 'windows' directories are self-contained, and can be copied to -//an existing Flutter project, enabling `flutter run` for those platforms. -// -//**Be aware that neither the API surface of the Flutter desktop libraries nor the -//interaction between the `flutter` tool and the platform directories is stable, -//and no attempt will be made to provide supported migration paths as things -//change.** You should expect that every time you update Flutter you may have -//to delete your copies of the platform directories and re-copy them from an -//updated version of flutter-desktop-embedding. -// -//### Customizing the Runners -// -//See [Application Customization](App-Customization.md) for premilinary -//documenation on modifying basic application information like name and icon. -// -//If you are building for macOS, you should also read about [managing macOS -//security configurations](../macOS-Security.md). diff --git a/example/lib/multi_select_style_page.dart b/example/lib/multi_select_style_page.dart index dfabfb1..0fa32ed 100644 --- a/example/lib/multi_select_style_page.dart +++ b/example/lib/multi_select_style_page.dart @@ -21,6 +21,7 @@ class _MultiSelectStylePageState extends State { @override void initState() { + super.initState(); controller = new CalendarController( selectMode: CalendarConstants.MODE_MULTI_SELECT, maxMultiSelectCount: 5, @@ -102,7 +103,7 @@ class _MultiSelectStylePageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["一", "二", "三", "四", "五", "六", "日"]; + final List weekList = ["一", "二", "三", "四", "五", "六", "日"]; @override Widget getWeekBarItem(int index) { @@ -119,7 +120,6 @@ class CustomStyleDayWidget extends BaseCustomDayWidget { @override void drawNormal(DateModel dateModel, Canvas canvas, Size size) { - bool isWeekend = dateModel.isWeekend; bool isInRange = dateModel.isInRange; //顶部的文字 diff --git a/example/lib/only_week_page.dart b/example/lib/only_week_page.dart index c9af7d3..68ec4ac 100644 --- a/example/lib/only_week_page.dart +++ b/example/lib/only_week_page.dart @@ -21,6 +21,7 @@ class _OnlyWeekPageState extends State { @override void initState() { + super.initState(); DateTime now = DateTime.now(); controller = new CalendarController( minYear: now.year, diff --git a/example/lib/progress_style_page.dart b/example/lib/progress_style_page.dart index a36bd80..f9d597e 100644 --- a/example/lib/progress_style_page.dart +++ b/example/lib/progress_style_page.dart @@ -22,6 +22,7 @@ class _ProgressStylePageState extends State { @override void initState() { + super.initState(); DateTime now = DateTime.now(); DateTime temp = DateTime(now.year, now.month, now.day); @@ -117,7 +118,7 @@ class _ProgressStylePageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["一", "二", "三", "四", "五", "六", "日"]; + final List weekList = ["一", "二", "三", "四", "五", "六", "日"]; @override Widget getWeekBarItem(int index) { diff --git a/example/lib/red_style_page.dart b/example/lib/red_style_page.dart index a9f4501..491a17e 100644 --- a/example/lib/red_style_page.dart +++ b/example/lib/red_style_page.dart @@ -22,6 +22,8 @@ class _RedStylePageState extends State { @override void initState() { + super.initState(); + controller = new CalendarController( showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK, extraDataMap: customExtraData); @@ -47,6 +49,7 @@ class _RedStylePageState extends State { @override Widget build(BuildContext context) { var calendarWidget = CalendarViewWidget( + itemSize: 40, calendarController: controller, margin: EdgeInsets.only(top: 20), weekBarItemWidgetBuilder: () { @@ -64,7 +67,7 @@ class _RedStylePageState extends State { color: Colors.white, padding: EdgeInsets.symmetric(horizontal: 20), child: new Column( - crossAxisAlignment: CrossAxisAlignment.stretch, + crossAxisAlignment:CrossAxisAlignment.stretch , children: [ SizedBox( height: 20, @@ -131,7 +134,7 @@ class _RedStylePageState extends State { } class CustomStyleWeekBarItem extends BaseWeekBar { - List weekList = ["M", "T", "W", "T", "F", "S", "S"]; + final List weekList = ["M", "T", "W", "T", "F", "S", "S"]; //可以直接重写build方法 @override @@ -168,10 +171,10 @@ class CustomStyleWeekBarItem extends BaseWeekBar { class CustomStyleDayWidget extends BaseCombineDayWidget { CustomStyleDayWidget(DateModel dateModel) : super(dateModel); - TextStyle normalTextStyle = + final TextStyle normalTextStyle = TextStyle(fontWeight: FontWeight.w700, color: Colors.black); - TextStyle noIsCurrentMonthTextStyle = + final TextStyle noIsCurrentMonthTextStyle = TextStyle(fontWeight: FontWeight.w700, color: Colors.grey); @override diff --git a/lib/utils/date_util.dart b/lib/utils/date_util.dart index 6f63d71..898200f 100644 --- a/lib/utils/date_util.dart +++ b/lib/utils/date_util.dart @@ -1,6 +1,3 @@ -import 'dart:developer'; -import 'dart:math'; - import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart'; diff --git a/lib/widget/base_day_view.dart b/lib/widget/base_day_view.dart index 17d0808..6ff32ec 100644 --- a/lib/widget/base_day_view.dart +++ b/lib/widget/base_day_view.dart @@ -56,7 +56,7 @@ class CustomDayWidgetPainter extends CustomPainter { * 通过组合widget创建item,只需实现相关的方法就可以 */ abstract class BaseCombineDayWidget extends StatelessWidget { - DateModel dateModel; + final DateModel dateModel; BaseCombineDayWidget(this.dateModel); diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index d8b1871..cc73ad0 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -16,20 +16,20 @@ import 'package:provider/provider.dart'; //由于旧的代码关系。。所以现在需要抽出一个StatefulWidget放在StatelessWidget里面 class CalendarViewWidget extends StatefulWidget { //整体的背景设置 - BoxDecoration boxDecoration; + final BoxDecoration boxDecoration; //日历的padding和margin - EdgeInsetsGeometry padding; - EdgeInsetsGeometry margin; + final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry margin; //默认是屏幕宽度/7 - double itemSize; + final double itemSize; //日历item之间的竖直方向间距,默认10 - double verticalSpacing; + final double verticalSpacing; - DayWidgetBuilder dayWidgetBuilder; - WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; + final DayWidgetBuilder dayWidgetBuilder; + final WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //控制器 final CalendarController calendarController; @@ -111,6 +111,7 @@ class CalendarContainerState extends State @override void initState() { + super.initState(); calendarProvider = Provider.of(context, listen: false); expand = calendarProvider.expandStatus.value; diff --git a/lib/widget/fast_click_widget.dart b/lib/widget/fast_click_widget.dart deleted file mode 100644 index afc3f16..0000000 --- a/lib/widget/fast_click_widget.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; - -/** - * 防止快速点击 - */ -class FastClickWidget extends StatelessWidget { - final int between_time = 500; //默认两次点击间隔500ms内则点击无效 - - Function onTap; - Widget child; - - FastClickWidget({@required this.onTap, @required this.child}); - - int lastClickTime = 0; - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: () { - if (lastClickTime == 0 || - DateTime.now().millisecondsSinceEpoch - lastClickTime > - between_time) { - onTap(); - lastClickTime = DateTime.now().millisecondsSinceEpoch; - } else { - //间隔500ms内点击无效 - } - }, - child: child, - ); - } -} diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 9c02b49..876a029 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/cache_data.dart'; diff --git a/lib/widget/month_view_pager.dart b/lib/widget/month_view_pager.dart index 358d442..a35e24f 100644 --- a/lib/widget/month_view_pager.dart +++ b/lib/widget/month_view_pager.dart @@ -1,10 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/configuration.dart'; -import 'package:flutter_custom_calendar/constants/constants.dart'; import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart'; -import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/widget/month_view.dart'; import 'package:provider/provider.dart'; @@ -21,6 +19,7 @@ class _MonthViewPagerState extends State @override void initState() { + super.initState(); LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager initState"); calendarProvider = Provider.of(context, listen: false); diff --git a/lib/widget/week_view.dart b/lib/widget/week_view.dart index 7542ffc..ddf910c 100644 --- a/lib/widget/week_view.dart +++ b/lib/widget/week_view.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/configuration.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'; import 'package:flutter_custom_calendar/widget/month_view.dart'; diff --git a/lib/widget/week_view_pager.dart b/lib/widget/week_view_pager.dart index ef9f06d..3a468c0 100644 --- a/lib/widget/week_view_pager.dart +++ b/lib/widget/week_view_pager.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/configuration.dart'; -import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/utils/LogUtil.dart'; import 'package:flutter_custom_calendar/widget/week_view.dart'; @@ -23,6 +22,7 @@ class _WeekViewPagerState extends State @override void initState() { + super.initState(); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager initState"); calendarProvider = Provider.of(context, listen: false); @@ -56,7 +56,8 @@ class _WeekViewPagerState extends State } LogUtil.log( TAG: this.runtimeType, - message: "WeekViewPager PageView onPageChanged:${position}"); + message: + "WeekViewPager PageView onPageChanged,position:$position"); // 周视图的变化 DateModel firstDayOfWeek = configuration.weekList[position]; int currentMonth = firstDayOfWeek.month; @@ -64,7 +65,7 @@ class _WeekViewPagerState extends State LogUtil.log( TAG: this.runtimeType, message: - "WeekViewPager PageView monthChange:currentMonth:${currentMonth}"); + "WeekViewPager PageView monthChange:currentMonth:$currentMonth"); configuration.monthChangeListeners.forEach((listener) { listener(firstDayOfWeek.year, firstDayOfWeek.month); }); From 390a826be45df6d7c4bd4dd1d6d4e88e49d07ae3 Mon Sep 17 00:00:00 2001 From: xiaodong <450468291@qq.com> Date: Sun, 3 Nov 2019 10:40:26 +0800 Subject: [PATCH 19/25] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=8B=B1=E6=96=87?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API_en.md | 339 ++++++++++++++++++++++++++++++++ example/lib/red_style_page.dart | 1 - 2 files changed, 339 insertions(+), 1 deletion(-) create mode 100644 API_en.md diff --git a/API_en.md b/API_en.md new file mode 100644 index 0000000..889ede0 --- /dev/null +++ b/API_en.md @@ -0,0 +1,339 @@ + +## Main API documents + +- [Main API documents](#%e4%b8%bb%e8%a6%81api%e6%96%87%e6%a1%a3) + - [Configure calendar UI](#%e9%85%8d%e7%bd%ae%e6%97%a5%e5%8e%86%e7%9a%84ui) + - [Parameter description](#%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e) + - [Configure controller](#%e9%85%8d%e7%bd%aecontroller) + - [Parameter description](#%e9%80%9a%e7%94%a8%e5%8f%82%e6%95%b0%e8%af%b4%e6%98%8e) + - [Add event listening to controller](#%e7%bb%99controller%e6%b7%bb%e5%8a%a0%e4%ba%8b%e4%bb%b6%e7%9b%91%e5%90%ac) + - [Using controller to control the switching of calendar and support the configuration of animation](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e6%8e%a7%e5%88%b6%e6%97%a5%e5%8e%86%e7%9a%84%e5%88%87%e6%8d%a2%e6%94%af%e6%8c%81%e9%85%8d%e7%bd%ae%e5%8a%a8%e7%94%bb) + - [Using controller to get the status and data of current calendar](#%e5%88%a9%e7%94%a8controller%e6%9d%a5%e8%8e%b7%e5%8f%96%e5%bd%93%e5%89%8d%e6%97%a5%e5%8e%86%e7%9a%84%e7%8a%b6%e6%80%81%e5%92%8c%e6%95%b0%e6%8d%ae) + - [How to customize UI](#%e5%a6%82%e4%bd%95%e8%87%aa%e5%ae%9a%e4%b9%89ui) + - [Customize weekbar](#%e8%87%aa%e5%ae%9a%e4%b9%89weekbar) + - [Custom calendar item](#%e8%87%aa%e5%ae%9a%e4%b9%89%e6%97%a5%e5%8e%86item) + - [Customize extra data extradata according to the actual scenario](#%e6%a0%b9%e6%8d%ae%e5%ae%9e%e9%99%85%e5%9c%ba%e6%99%af%e8%87%aa%e5%ae%9a%e4%b9%89%e9%a2%9d%e5%a4%96%e7%9a%84%e6%95%b0%e6%8d%aeextradata) + - [Calendar with progress bar style](#%e5%ae%9e%e7%8e%b0%e8%bf%9b%e5%ba%a6%e6%9d%a1%e6%a0%b7%e5%bc%8f%e7%9a%84%e6%97%a5%e5%8e%86) + - [Implement custom calendars for various tags](#%e5%ae%9e%e7%8e%b0%e8%87%aa%e5%ae%9a%e4%b9%89%e5%90%84%e7%a7%8d%e6%a0%87%e8%ae%b0%e7%9a%84%e6%97%a5%e5%8e%86) + - [Modify customized data manually](#%e6%89%8b%e5%8a%a8%e4%bf%ae%e6%94%b9%e8%87%aa%e5%ae%9a%e4%b9%89%e7%9a%84%e6%95%b0%e6%8d%ae) + - [DateModel Entry](#datemodel%e5%ae%9e%e4%bd%93%e7%b1%bb) + +### Configure calendar UI + +The configuration of calendar UI is done in the constructor of calendarviewwidget. +``` + CalendarViewWidget( + {Key key, + this.dayWidgetBuilder = defaultCustomDayWidget, + this.weekBarItemWidgetBuilder = defaultWeekBarWidget, + @required this.calendarController, + this.boxDecoration, + this.padding = EdgeInsets.zero, + this.margin = EdgeInsets.zero, + this.verticalSpacing = 10, + this.itemSize}) + : super(key: key); +``` +#### Parameter description + +| Attribute | Meaning | Default value | +| :----------------------: | :------------------------: | :--------------------------------------: | +| weekBarItemWidgetBuilder | Create the weekbar at the top | Default style | +| dayWidgetBuilder | Create calendar item | Default style | +| verticalSpacing | Vertical spacing between calendar items | Default is 10 | +| boxDecoration | calendar background setting | Default is null | +| itemSize | Size of each item | The default screen width of mobile phone / 7, and the default screen height of web page / 7 | +| padding | Calendar padding | EdgeInsets.zero | +| margin | Calendar padding | EdgeInsets.zero | + + + +### Configure controller +Two action: +One is to display the related data required by the calendar, which is configured in the controller. +One is to use the controller to add event monitoring and use the controller to operate the calendar. + +``` + //构造函数 + CalendarController( + {int selectMode = CalendarConstants.MODE_SINGLE_SELECT, + int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH, + int minYear = 1971, + int maxYear = 2055, + int minYearMonth = 1, + int maxYearMonth = 12, + int nowYear, + int nowMonth, + int minSelectYear = 1971, + int minSelectMonth = 1, + int minSelectDay = 1, + int maxSelectYear = 2055, + int maxSelectMonth = 12, + int maxSelectDay = 30, + Set selectedDateTimeList = EMPTY_SET, + DateModel selectDateModel, + int maxMultiSelectCount = 9999, + Map extraDataMap = EMPTY_MAP}) +``` + +#### General parameter description + +| Attribute | Meaning | Default value | +| :-----------------: | :-----------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | +| selectMode | Selection mode, indicating single selection or multiple selection | default is single select
static const int MODE_SINGLE_SELECT = 1;
static const int MODE_MULTI_SELECT = 2; | +| showMode | Display mode | 默认是只展示月视图
static const int MODE_SHOW_ONLY_MONTH=1;//仅支持月视图
static const int MODE_SHOW_ONLY_WEEK=2;//仅支持星期视图
static const int MODE_SHOW_WEEK_AND_MONTH=3;//支持两种视图,先显示周视图
static const int MODE_SHOW_MONTH_AND_WEEK=4;//支持两种视图,先显示月视图 | +| minYear | Minimum year for calendar display | 1971 | +| maxYear | Maximum year displayed in calendar | 2055 | +| minYearMonth | The month of the smallest year displayed by the calendar | 1 | +| maxYearMonth | The month of the largest year displayed by the calendar | 12 | +| nowYear | Current year displayed by calendar | -1 | +| nowMonth | Current month displayed by calendar | -1 | +| minSelectYear | Minimum year that can be selected | 1971 | +| minSelectMonth | Month of the smallest year that can be selected | 1 | +| minSelectDay | The day of the smallest month you can choose | 1 | +| maxSelectYear | Maximum year that can be selected | 2055 | +| maxSelectMonth | Month of the largest year you can choose | 12 | +| maxSelectDay | The day of the largest month you can choose | 30,注意:不能超过对应月份的总天数 | +| selectedDateList | Selected date for multiple selections | 默认为空Set, Set selectedDateList = new Set() | +| selectDateModel | Current selection, for radio selection | 默认为空 | +| maxMultiSelectCount | Multiple choice, how many at most | hhh | +| extraDataMap | Customize additional data | 默认为空Map,Map extraDataMap = new Map() | + + +#### Add event listening to controller + +| Method | Meaning | Default value | +| :-----------------------------------------------------------------------: | :--------------------: | :----: | +| void addMonthChangeListener(OnMonthChange listener) | Month switching event | +| void addOnCalendarSelectListener(OnCalendarSelect listener) | Click to select an event | +| void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | Multiple selection out of the specified range | +| void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | Multiple selection exceeds the limit | +| void addExpandChangeListener(ValueChanged expandChange) | Monitor the expansion and contraction status of calendar | + +#### Using controller to control the switching of calendar and support the configuration of animation + +| Method | Meaning | Default value | +| :-------------------------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------------------: | :----: | +| Future previousPage() | Sliding to the previous page will automatically slide to the previous month or week according to the current deployment status. If it is already on the first page and there is no previous page, it will return false, otherwise it will return true | +| Future nextPage() | Sliding to the next page will automatically move to the next month or week according to the current deployment status. If it is already on the last page and there is no next page, it will return false, otherwise it will return true | +| void moveToCalendar(int year, int month, int day, {bool needAnimation = false,Duration duration = const Duration(milliseconds: 500),Curve curve = Curves.ease}) | To specified date | +| void moveToNextYear() | Switch to next year | +| void moveToPreviousYear() | Switch to previous year | +| void moveToNextMonth() | Switch to the next month | +| void moveToPreviousMonth() | Switch to previous month | +| void toggleExpandStatus() | Toggle deployment state | +| void changeExtraData(Map newMap) | Modify custom extra data and refresh calendar | + + +#### Using controller to get the status and data of current calendar + +| Method | Meaning | Default Value | +| :-------------------------------------: | :--------------------: | :----: | +| DateTime getCurrentMonth() | Get the current month | +| Set getMultiSelectCalendar() | Get selected date,multiple choices | +| DateModel getSingleSelectCalendar() | Get selected date,single choiice | + + + +### How to customize UI + +Including custom weekbar and custom calendar item. Defaultxxwidget is used by default. + +As long as we inherit the corresponding base class and implement the corresponding methods, then we only need to implement the corresponding builder methods when configuring the controller. + +``` +//支持自定义绘制 +DayWidgetBuilder dayWidgetBuilder; //create calendar item +WeekBarItemWidgetBuilder weekBarItemWidgetBuilder; //create weekbar +``` +#### Customize weekbar + +The first way is to inherit baseweekbar and override getweekbaritem (index) method. Whatever you do, just return a 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, + ), + ); + } +} +``` +In the second way, you can directly rewrite the build method for more custom drawing. + +``` +class CustomStyleWeekBarItem extends BaseWeekBar { + List weekList = ["mo", "tu", "we", "th", "fr", "sa", "su"]; + + //可以直接重写build方法,weekbar底部添加下划线 + @override + Widget build(BuildContext context) { + List children = List(); + + var items = getWeekDayWidget(); + children.add(Row( + children: items, + )); + children.add(Divider( + color: Colors.grey, + )); + return Column( + children: children, + ); + } + + @override + Widget getWeekBarItem(int index) { + return new Container( + margin: EdgeInsets.only(top: 10, bottom: 10), + child: new Center( + child: new Text( + weekList[index], + style: + TextStyle(fontWeight: FontWeight.w700, color: Color(0xffC5BCDC)), + ), + ), + ); + } +} +``` + + +#### Custom calendar item: +There are two methods, one is to create by combining widgets, and the other is to draw items by using canvas. Finally, you only need to configure in the construction parameters of the calendarcontroller。 + +* Create by combining widgets: inherit basecombinedaywidget, rewrite getnormalwidget (datemodel datemodel) and getselectedwidget (datemodel datemodel), and return the corresponding widget. + +``` +class DefaultCombineDayWidget extends BaseCombineDayWidget { + DefaultCombineDayWidget(DateModel dateModel) : super(dateModel); + + @override + Widget getNormalWidget(DateModel dateModel) { + //实现默认状态下的UI + } + + @override + Widget getSelectedWidget(DateModel dateModel) { + //绘制被选中的UI + } +} +``` + + +* Use canvas to define drawing, inherit basecustomdaywidget, rewrite drawnormal and drawselected, and draw item by yourself. + +``` +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); + } +} +``` + +### Customize extra data extradata according to the actual scenario + +#### Calendar with progress bar style + +We can customize the progress bar data of each item, save it in the map, and finally assign it to the extradatamap of the controller +``` + //Externally process the tag corresponding to each datemodel + Map progressMap = { + DateModel.fromDateTime(temp.add(Duration(days: 1))): 0, + DateModel.fromDateTime(temp.add(Duration(days: 2))): 20, + DateModel.fromDateTime(temp.add(Duration(days: 3))): 40, + DateModel.fromDateTime(temp.add(Duration(days: 4))): 60, + DateModel.fromDateTime(temp.add(Duration(days: 5))): 80, + DateModel.fromDateTime(temp.add(Duration(days: 6))): 100, + }; + //When creating the calendarcontroller object, assign the extradatamap + new CalendarController( + extraDataMap: progressMap) + //When drawing daywidget, you can get the desired data directly from the extradata object of datemodel + int progress = dateModel.extraData; +``` + +#### Implement custom calendars for various tags +``` + //Externally process the tag corresponding to each datemodel + Map customExtraData = { + DateModel.fromDateTime(DateTime.now().add(Duration(days: -1))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -2))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -3))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -4))): "班", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -5))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: -6))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 2))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 3))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 4))): "班", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 5))): "假", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 6))): "游", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 7))): "事", + DateModel.fromDateTime(DateTime.now().add(Duration(days: 8))): "班", + }; + //When creating the calendarcontroller object, assign the extradatamap + new CalendarController( + extraDataMap: customExtraData) + //When drawing daywidget, you can get the desired data directly from the extradata object of datemodel + String data = dateModel.extraData; +``` + +#### Modify customized data manually + +When the customized data changes, you can use the controller's change extradata (map < datemodel, Object > NewMap) method,The calendar will refresh automatically and draw based on the new additional data + +``` + //可以动态修改extraDataMap + void changeExtraData(Map newMap) { + this.calendarConfiguration.extraDataMap = newMap; + this.calendarProvider.generation.value++; + } +``` + +### DateModel Entry +The entity class datemodel of the date used by the calendar has the following properties. You can draw the corresponding UI after judging according to the corresponding properties when you customize the daywidget. + +| Attribute | Meaning | Type | Default Value | +| :---------------: | :---------------------------------------------------: | :----: | :------: | +| year | 年份 | int | +| month | 月份 | int | +| day | 日期 | int | 默认为1 | +| lunarYear | 农历年份 | int | +| lunarMonth | 农历月份 | int | +| lunarDay | 农历日期 | int | +| lunarString | 农历字符串 | String | +| solarTerm | 24 solar terms | String | +| gregorianFestival | gregorianFestival | String | +| traditionFestival | 传统农历节日 | String | +| isCurrentDay | 是否是今天 | bool | false | +| isLeapYear | 是否是闰年 | bool | false | +| isWeekend | 是否是周末 | bool | false | +| isInRange | Whether it is in the range, for example, it can set the gray function outside a range | bool | false | +| isSelected | Is it selected to implement some marking or selection functions | bool | false | +| extraData | Custom extra data | Object | 默认为空 | +| isCurrentMonth | 是否是当前月份 | bool | + + +| Method | Meaning | +| :---------------------------------------: | :-------------------------------------------------------: | +| DateTime getDateTime() | Convert datemodel to datetime | +| DateModel fromDateTime(DateTime dateTime) | Create corresponding model according to datetime, and initialize information such as lunar calendar and traditional festivals | +| bool operator ==(Object other) | Override the = = method to determine whether two datemodels are the same day | \ No newline at end of file diff --git a/example/lib/red_style_page.dart b/example/lib/red_style_page.dart index 491a17e..e3801c7 100644 --- a/example/lib/red_style_page.dart +++ b/example/lib/red_style_page.dart @@ -49,7 +49,6 @@ class _RedStylePageState extends State { @override Widget build(BuildContext context) { var calendarWidget = CalendarViewWidget( - itemSize: 40, calendarController: controller, margin: EdgeInsets.only(top: 20), weekBarItemWidgetBuilder: () { 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 20/25] =?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 From 72445bb81348aa0c26f4bc14ffa06e61770e51d6 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Mon, 4 Nov 2019 16:13:17 +0800 Subject: [PATCH 21/25] =?UTF-8?q?=E6=9B=B4=E6=96=B0provider=E5=BA=93?= =?UTF-8?q?=EF=BC=8C=E6=9C=80=E6=96=B0=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 52eb617..8d075d6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,7 +10,7 @@ environment: dependencies: flutter: sdk: flutter - provider: 3.0.0+1 + provider: ^3.1.0+1 dev_dependencies: flutter_test: sdk: flutter From 17c2a74fbb9d8637655bf1b6c67074a7b55f5653 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 5 Nov 2019 10:07:07 +0800 Subject: [PATCH 22/25] =?UTF-8?q?example=E9=80=82=E9=85=8DAndroidX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/.gitignore | 63 +-- example/.metadata | 6 +- example/README.md | 16 +- example/android/.gitignore | 7 + example/android/app/build.gradle | 67 +++ .../android/app/src/debug/AndroidManifest.xml | 7 + .../android/app/src/main/AndroidManifest.xml | 32 ++ .../com/example/example1/MainActivity.kt | 12 + .../main/res/drawable/launch_background.xml | 12 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../app/src/main/res/values/styles.xml | 8 + .../app/src/profile/AndroidManifest.xml | 7 + example/android/build.gradle | 31 ++ example/android/gradle.properties | 4 + .../gradle/wrapper/gradle-wrapper.properties | 6 + example/android/settings.gradle | 15 + example/example.iml | 17 - example/example_android.iml | 27 - example/ios/.gitignore | 32 ++ example/ios/Flutter/AppFrameworkInfo.plist | 26 + example/ios/Flutter/Debug.xcconfig | 1 + example/ios/Flutter/Release.xcconfig | 1 + example/ios/Runner.xcodeproj/project.pbxproj | 518 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/xcschemes/Runner.xcscheme | 91 +++ .../contents.xcworkspacedata | 7 + example/ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 10932 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 564 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1588 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 1025 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1716 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 1920 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1283 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 1895 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 2665 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 3831 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 1888 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 3294 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 3612 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + .../Runner/Base.lproj/LaunchScreen.storyboard | 37 ++ example/ios/Runner/Base.lproj/Main.storyboard | 26 + example/ios/Runner/Info.plist | 45 ++ example/ios/Runner/Runner-Bridging-Header.h | 1 + example/lib/custom_style_page.dart | 3 +- example/lib/default_style_page.dart | 4 +- example/lib/main.dart | 6 +- example/pubspec.lock | 2 +- example/pubspec.yaml | 39 +- example/test/widget_test.dart | 2 +- example/web/index.html | 2 +- pubspec.lock | 59 +- 64 files changed, 1281 insertions(+), 128 deletions(-) create mode 100644 example/android/.gitignore create mode 100644 example/android/app/build.gradle create mode 100644 example/android/app/src/debug/AndroidManifest.xml create mode 100644 example/android/app/src/main/AndroidManifest.xml create mode 100644 example/android/app/src/main/kotlin/com/example/example1/MainActivity.kt create mode 100644 example/android/app/src/main/res/drawable/launch_background.xml create mode 100644 example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 example/android/app/src/main/res/values/styles.xml create mode 100644 example/android/app/src/profile/AndroidManifest.xml create mode 100644 example/android/build.gradle create mode 100644 example/android/gradle.properties create mode 100644 example/android/gradle/wrapper/gradle-wrapper.properties create mode 100644 example/android/settings.gradle delete mode 100644 example/example.iml delete mode 100644 example/example_android.iml create mode 100644 example/ios/.gitignore create mode 100644 example/ios/Flutter/AppFrameworkInfo.plist create mode 100644 example/ios/Flutter/Debug.xcconfig create mode 100644 example/ios/Flutter/Release.xcconfig create mode 100644 example/ios/Runner.xcodeproj/project.pbxproj create mode 100644 example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 example/ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 example/ios/Runner/AppDelegate.swift create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 example/ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 example/ios/Runner/Base.lproj/Main.storyboard create mode 100644 example/ios/Runner/Info.plist create mode 100644 example/ios/Runner/Runner-Bridging-Header.h diff --git a/example/.gitignore b/example/.gitignore index cdecf14..437cb45 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -1,41 +1,36 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp .DS_Store -.dart_tool/ - -.packages -.pub/ - -.idea/ -.vagrant/ -.sconsign.dblite +.atom/ +.buildlog/ +.history .svn/ -*.swp -profile - -DerivedData/ - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ -xcuserdata +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ -*.moved-aside +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +/build/ -*.pyc -*sync/ -Icon? -.tags* +# Web related +lib/generated_plugin_registrant.dart -build/ -.android/ -.ios/ -.flutter-plugins +# Exceptions to above rules. +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/example/.metadata b/example/.metadata index 4ce24c3..65c8fc6 100644 --- a/example/.metadata +++ b/example/.metadata @@ -4,7 +4,7 @@ # This file should be version controlled and should not be manually edited. version: - revision: 7a4c33425ddd78c54aba07d86f3f9a4a0051769b - channel: beta + revision: 0120c414fbc5d11c503e2091f420c02ffd6dda67 + channel: master -project_type: module +project_type: app diff --git a/example/README.md b/example/README.md index 3e6642f..292f0eb 100644 --- a/example/README.md +++ b/example/README.md @@ -1,8 +1,16 @@ -# example +# example1 -A new Flutter module. +A new Flutter project. ## Getting Started -For help getting started with Flutter, view our online -[documentation](https://flutter.dev/). +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/example/android/.gitignore b/example/android/.gitignore new file mode 100644 index 0000000..bc2100d --- /dev/null +++ b/example/android/.gitignore @@ -0,0 +1,7 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle new file mode 100644 index 0000000..4cea380 --- /dev/null +++ b/example/android/app/build.gradle @@ -0,0 +1,67 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 28 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + lintOptions { + disable 'InvalidPackage' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.example1" + minSdkVersion 16 + targetSdkVersion 28 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig signingConfigs.debug + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' +} diff --git a/example/android/app/src/debug/AndroidManifest.xml b/example/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..5163c1f --- /dev/null +++ b/example/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..28cf94a --- /dev/null +++ b/example/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + diff --git a/example/android/app/src/main/kotlin/com/example/example1/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/example1/MainActivity.kt new file mode 100644 index 0000000..c220bc3 --- /dev/null +++ b/example/android/app/src/main/kotlin/com/example/example1/MainActivity.kt @@ -0,0 +1,12 @@ +package com.example.example1 + +import android.os.Bundle +import io.flutter.app.FlutterActivity +import io.flutter.plugins.GeneratedPluginRegistrant + +class MainActivity: FlutterActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + GeneratedPluginRegistrant.registerWith(this) + } +} diff --git a/example/android/app/src/main/res/drawable/launch_background.xml b/example/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/example/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@Uy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/example/android/app/src/main/res/values/styles.xml b/example/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..00fa441 --- /dev/null +++ b/example/android/app/src/main/res/values/styles.xml @@ -0,0 +1,8 @@ + + + + diff --git a/example/android/app/src/profile/AndroidManifest.xml b/example/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..5163c1f --- /dev/null +++ b/example/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/example/android/build.gradle b/example/android/build.gradle new file mode 100644 index 0000000..3100ad2 --- /dev/null +++ b/example/android/build.gradle @@ -0,0 +1,31 @@ +buildscript { + ext.kotlin_version = '1.3.50' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:3.5.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/example/android/gradle.properties b/example/android/gradle.properties new file mode 100644 index 0000000..38c8d45 --- /dev/null +++ b/example/android/gradle.properties @@ -0,0 +1,4 @@ +org.gradle.jvmargs=-Xmx1536M +android.enableR8=true +android.useAndroidX=true +android.enableJetifier=true diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..296b146 --- /dev/null +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/example/android/settings.gradle b/example/android/settings.gradle new file mode 100644 index 0000000..5a2f14f --- /dev/null +++ b/example/android/settings.gradle @@ -0,0 +1,15 @@ +include ':app' + +def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() + +def plugins = new Properties() +def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') +if (pluginsFile.exists()) { + pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } +} + +plugins.each { name, path -> + def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() + include ":$name" + project(":$name").projectDir = pluginDirectory +} diff --git a/example/example.iml b/example/example.iml deleted file mode 100644 index c92516a..0000000 --- a/example/example.iml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/example/example_android.iml b/example/example_android.iml deleted file mode 100644 index 8d91e24..0000000 --- a/example/example_android.iml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/example/ios/.gitignore b/example/ios/.gitignore new file mode 100644 index 0000000..e96ef60 --- /dev/null +++ b/example/ios/.gitignore @@ -0,0 +1,32 @@ +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..6b4c0f7 --- /dev/null +++ b/example/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 8.0 + + diff --git a/example/ios/Flutter/Debug.xcconfig b/example/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/example/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/example/ios/Flutter/Release.xcconfig b/example/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/example/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..23d3283 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,518 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, + 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, + 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B80C3931E831B6300D905FE /* App.framework */, + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEBA1CF902C7004384FC /* Flutter.framework */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 97C146F11CF9000F007C117D /* Supporting Files */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + 97C146F11CF9000F007C117D /* Supporting Files */ = { + isa = PBXGroup; + children = ( + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1020; + ORGANIZATIONNAME = "The Chromium Authors"; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Flutter", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.example1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..a28140c --- /dev/null +++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner.xcworkspace/contents.xcworkspacedata b/example/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/example/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/example/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..dc9ada4725e9b0ddb1deab583e5b5102493aa332 GIT binary patch literal 10932 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f091b6b0bca859a3f474b03065bef75ba58a9e4c GIT binary patch literal 1588 zcmV-42Fv-0P)C1SqPt}wig>|5Crh^=oyX$BK<}M8eLU3e2hGT;=G|!_SP)7zNI6fqUMB=)y zRAZ>eDe#*r`yDAVgB_R*LB*MAc)8(b{g{9McCXW!lq7r(btRoB9!8B-#AI6JMb~YFBEvdsV)`mEQO^&#eRKx@b&x- z5lZm*!WfD8oCLzfHGz#u7sT0^VLMI1MqGxF^v+`4YYnVYgk*=kU?HsSz{v({E3lb9 z>+xILjBN)t6`=g~IBOelGQ(O990@BfXf(DRI5I$qN$0Gkz-FSc$3a+2fX$AedL4u{ z4V+5Ong(9LiGcIKW?_352sR;LtDPmPJXI{YtT=O8=76o9;*n%_m|xo!i>7$IrZ-{l z-x3`7M}qzHsPV@$v#>H-TpjDh2UE$9g6sysUREDy_R(a)>=eHw-WAyfIN z*qb!_hW>G)Tu8nSw9yn#3wFMiLcfc4pY0ek1}8(NqkBR@t4{~oC>ryc-h_ByH(Cg5 z>ao-}771+xE3um9lWAY1FeQFxowa1(!J(;Jg*wrg!=6FdRX+t_<%z&d&?|Bn){>zm zZQj(aA_HeBY&OC^jj*)N`8fa^ePOU72VpInJoI1?`ty#lvlNzs(&MZX+R%2xS~5Kh zX*|AU4QE#~SgPzOXe9>tRj>hjU@c1k5Y_mW*Jp3fI;)1&g3j|zDgC+}2Q_v%YfDax z!?umcN^n}KYQ|a$Lr+51Nf9dkkYFSjZZjkma$0KOj+;aQ&721~t7QUKx61J3(P4P1 zstI~7-wOACnWP4=8oGOwz%vNDqD8w&Q`qcNGGrbbf&0s9L0De{4{mRS?o0MU+nR_! zrvshUau0G^DeMhM_v{5BuLjb#Hh@r23lDAk8oF(C+P0rsBpv85EP>4CVMx#04MOfG z;P%vktHcXwTj~+IE(~px)3*MY77e}p#|c>TD?sMatC0Tu4iKKJ0(X8jxQY*gYtxsC z(zYC$g|@+I+kY;dg_dE>scBf&bP1Nc@Hz<3R)V`=AGkc;8CXqdi=B4l2k|g;2%#m& z*jfX^%b!A8#bI!j9-0Fi0bOXl(-c^AB9|nQaE`*)Hw+o&jS9@7&Gov#HbD~#d{twV zXd^Tr^mWLfFh$@Dr$e;PBEz4(-2q1FF0}c;~B5sA}+Q>TOoP+t>wf)V9Iy=5ruQa;z)y zI9C9*oUga6=hxw6QasLPnee@3^Rr*M{CdaL5=R41nLs(AHk_=Y+A9$2&H(B7!_pURs&8aNw7?`&Z&xY_Ye z)~D5Bog^td-^QbUtkTirdyK^mTHAOuptDflut!#^lnKqU md>ggs(5nOWAqO?umG&QVYK#ibz}*4>0000U6E9hRK9^#O7(mu>ETqrXGsduA8$)?`v2seloOCza43C{NQ$$gAOH**MCn0Q?+L7dl7qnbRdqZ8LSVp1ItDxhxD?t@5_yHg6A8yI zC*%Wgg22K|8E#!~cTNYR~@Y9KepMPrrB8cABapAFa=`H+UGhkXUZV1GnwR1*lPyZ;*K(i~2gp|@bzp8}og7e*#% zEnr|^CWdVV!-4*Y_7rFvlww2Ze+>j*!Z!pQ?2l->4q#nqRu9`ELo6RMS5=br47g_X zRw}P9a7RRYQ%2Vsd0Me{_(EggTnuN6j=-?uFS6j^u69elMypu?t>op*wBx<=Wx8?( ztpe^(fwM6jJX7M-l*k3kEpWOl_Vk3@(_w4oc}4YF4|Rt=2V^XU?#Yz`8(e?aZ@#li0n*=g^qOcVpd-Wbok=@b#Yw zqn8u9a)z>l(1kEaPYZ6hwubN6i<8QHgsu0oE) ziJ(p;Wxm>sf!K+cw>R-(^Y2_bahB+&KI9y^);#0qt}t-$C|Bo71lHi{_+lg#f%RFy z0um=e3$K3i6K{U_4K!EX?F&rExl^W|G8Z8;`5z-k}OGNZ0#WVb$WCpQu-_YsiqKP?BB# vzVHS-CTUF4Ozn5G+mq_~Qqto~ahA+K`|lyv3(-e}00000NkvXXu0mjfd`9t{ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d0ef06e7edb86cdfe0d15b4b0d98334a86163658 GIT binary patch literal 1716 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..c8f9ed8f5cee1c98386d13b17e89f719e83555b2 GIT binary patch literal 1895 zcmV-t2blPYP)FQtfgmafE#=YDCq`qUBt#QpG%*H6QHY765~R=q zZ6iudfM}q!Pz#~9JgOi8QJ|DSu?1-*(kSi1K4#~5?#|rh?sS)(-JQqX*}ciXJ56_H zdw=^s_srbAdqxlvGyrgGet#6T7_|j;95sL%MtM;q86vOxKM$f#puR)Bjv9Zvz9-di zXOTSsZkM83)E9PYBXC<$6(|>lNLVBb&&6y{NByFCp%6+^ALR@NCTse_wqvNmSWI-m z!$%KlHFH2omF!>#%1l3LTZg(s7eof$7*xB)ZQ0h?ejh?Ta9fDv59+u#MokW+1t8Zb zgHv%K(u9G^Lv`lh#f3<6!JVTL3(dCpxHbnbA;kKqQyd1~^Xe0VIaYBSWm6nsr;dFj z4;G-RyL?cYgsN1{L4ZFFNa;8)Rv0fM0C(~Tkit94 zz#~A)59?QjD&pAPSEQ)p8gP|DS{ng)j=2ux)_EzzJ773GmQ_Cic%3JJhC0t2cx>|v zJcVusIB!%F90{+}8hG3QU4KNeKmK%T>mN57NnCZ^56=0?&3@!j>a>B43pi{!u z7JyDj7`6d)qVp^R=%j>UIY6f+3`+qzIc!Y_=+uN^3BYV|o+$vGo-j-Wm<10%A=(Yk^beI{t%ld@yhKjq0iNjqN4XMGgQtbKubPM$JWBz}YA65k%dm*awtC^+f;a-x4+ddbH^7iDWGg&N0n#MW{kA|=8iMUiFYvMoDY@sPC#t$55gn6ykUTPAr`a@!(;np824>2xJthS z*ZdmT`g5-`BuJs`0LVhz+D9NNa3<=6m;cQLaF?tCv8)zcRSh66*Z|vXhG@$I%U~2l z?`Q zykI#*+rQ=z6Jm=Bui-SfpDYLA=|vzGE(dYm=OC8XM&MDo7ux4UF1~0J1+i%aCUpRe zt3L_uNyQ*cE(38Uy03H%I*)*Bh=Lb^Xj3?I^Hnbeq72(EOK^Y93CNp*uAA{5Lc=ky zx=~RKa4{iTm{_>_vSCm?$Ej=i6@=m%@VvAITnigVg{&@!7CDgs908761meDK5azA} z4?=NOH|PdvabgJ&fW2{Mo$Q0CcD8Qc84%{JPYt5EiG{MdLIAeX%T=D7NIP4%Hw}p9 zg)==!2Lbp#j{u_}hMiao9=!VSyx0gHbeCS`;q&vzeq|fs`y&^X-lso(Ls@-706qmA z7u*T5PMo_w3{se1t2`zWeO^hOvTsohG_;>J0wVqVe+n)AbQCx)yh9;w+J6?NF5Lmo zecS@ieAKL8%bVd@+-KT{yI|S}O>pYckUFs;ry9Ow$CD@ztz5K-*D$^{i(_1llhSh^ zEkL$}tsQt5>QA^;QgjgIfBDmcOgi5YDyu?t6vSnbp=1+@6D& z5MJ}B8q;bRlVoxasyhcUF1+)o`&3r0colr}QJ3hcSdLu;9;td>kf@Tcn<@9sIx&=m z;AD;SCh95=&p;$r{Xz3iWCO^MX83AGJ(yH&eTXgv|0=34#-&WAmw{)U7OU9!Wz^!7 zZ%jZFi@JR;>Mhi7S>V7wQ176|FdW2m?&`qa(ScO^CFPR80HucLHOTy%5s*HR0^8)i h0WYBP*#0Ks^FNSabJA*5${_#%002ovPDHLkV1oKhTl@e3 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d6b8609df07bf62e5100a53a01510388bd2b22 GIT binary patch literal 2665 zcmV-v3YPVWP)oFh3q0MFesq&64WThn3$;G69TfjsAv=f2G9}p zgSx99+!YV6qME!>9MD13x)k(+XE7W?_O4LoLb5ND8 zaV{9+P@>42xDfRiYBMSgD$0!vssptcb;&?u9u(LLBKmkZ>RMD=kvD3h`sk6!QYtBa ztlZI#nu$8lJ^q2Z79UTgZe>BU73(Aospiq+?SdMt8lDZ;*?@tyWVZVS_Q7S&*tJaiRlJ z+aSMOmbg3@h5}v;A*c8SbqM3icg-`Cnwl;7Ts%A1RkNIp+Txl-Ckkvg4oxrqGA5ewEgYqwtECD<_3Egu)xGllKt&J8g&+=ac@Jq4-?w6M3b*>w5 z69N3O%=I^6&UL5gZ!}trC7bUj*12xLdkNs~Bz4QdJJ*UDZox2UGR}SNg@lmOvhCc~ z*f_UeXv(=#I#*7>VZx2ObEN~UoGUTl=-@)E;YtCRZ>SVp$p9yG5hEFZ!`wI!spd)n zSk+vK0Vin7FL{7f&6OB%f;SH22dtbcF<|9fi2Fp%q4kxL!b1#l^)8dUwJ zwEf{(wJj@8iYDVnKB`eSU+;ml-t2`@%_)0jDM`+a46xhDbBj2+&Ih>1A>6aky#(-SYyE{R3f#y57wfLs z6w1p~$bp;6!9DX$M+J~S@D6vJAaElETnsX4h9a5tvPhC3L@qB~bOzkL@^z0k_hS{T4PF*TDrgdXp+dzsE? z>V|VR035Pl9n5&-RePFdS{7KAr2vPOqR9=M$vXA1Yy5>w;EsF`;OK{2pkn-kpp9Pw z)r;5JfJKKaT$4qCb{TaXHjb$QA{y0EYy*+b1XI;6Ah- zw13P)xT`>~eFoJC!>{2XL(a_#upp3gaR1#5+L(Jmzp4TBnx{~WHedpJ1ch8JFk~Sw z>F+gN+i+VD?gMXwcIhn8rz`>e>J^TI3E-MW>f}6R-pL}>WMOa0k#jN+`RyUVUC;#D zg|~oS^$6%wpF{^Qr+}X>0PKcr3Fc&>Z>uv@C);pwDs@2bZWhYP!rvGx?_|q{d`t<*XEb#=aOb=N+L@CVBGqImZf&+a zCQEa3$~@#kC);pasdG=f6tuIi0PO-y&tvX%>Mv=oY3U$nD zJ#gMegnQ46pq+3r=;zmgcG+zRc9D~c>z+jo9&D+`E6$LmyFqlmCYw;-Zooma{sR@~ z)_^|YL1&&@|GXo*pivH7k!msl+$Sew3%XJnxajt0K%3M6Bd&YFNy9}tWG^aovK2eX z1aL1%7;KRDrA@eG-Wr6w+;*H_VD~qLiVI`{_;>o)k`{8xa3EJT1O_>#iy_?va0eR? zDV=N%;Zjb%Z2s$@O>w@iqt!I}tLjGk!=p`D23I}N4Be@$(|iSA zf3Ih7b<{zqpDB4WF_5X1(peKe+rASze%u8eKLn#KKXt;UZ+Adf$_TO+vTqshLLJ5c z52HucO=lrNVae5XWOLm!V@n-ObU11!b+DN<$RuU+YsrBq*lYT;?AwJpmNKniF0Q1< zJCo>Q$=v$@&y=sj6{r!Y&y&`0$-I}S!H_~pI&2H8Z1C|BX4VgZ^-! zje3-;x0PBD!M`v*J_)rL^+$<1VJhH*2Fi~aA7s&@_rUHYJ9zD=M%4AFQ`}k8OC$9s XsPq=LnkwKG00000NkvXXu0mjfhAk5^ literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..75b2d164a5a98e212cca15ea7bf2ab5de5108680 GIT binary patch literal 3831 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 literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c4df70d39da7941ef3f6dcb7f06a192d8dcb308d GIT binary patch literal 1888 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 iW8Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/example/ios/Runner/Base.lproj/LaunchScreen.storyboard b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/example/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Base.lproj/Main.storyboard b/example/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/example/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist new file mode 100644 index 0000000..b5ab635 --- /dev/null +++ b/example/ios/Runner/Info.plist @@ -0,0 +1,45 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + example1 + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/example/ios/Runner/Runner-Bridging-Header.h b/example/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..7335fdf --- /dev/null +++ b/example/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" \ No newline at end of file diff --git a/example/lib/custom_style_page.dart b/example/lib/custom_style_page.dart index 3aec4c9..400b98d 100644 --- a/example/lib/custom_style_page.dart +++ b/example/lib/custom_style_page.dart @@ -22,7 +22,8 @@ class _CustomStylePageState extends State { @override void initState() { super.initState(); - controller = new CalendarController(); + controller = new CalendarController( + selectDateModel: DateModel.fromDateTime(DateTime.now())); controller.addMonthChangeListener( (year, month) { diff --git a/example/lib/default_style_page.dart b/example/lib/default_style_page.dart index bb20ddd..5546b96 100644 --- a/example/lib/default_style_page.dart +++ b/example/lib/default_style_page.dart @@ -24,9 +24,9 @@ class _DefaultStylePageState extends State { super.initState(); DateTime now = DateTime.now(); controller = new CalendarController( - minYear: now.year-1, + minYear: now.year - 1, minYearMonth: 1, - maxYear: now.year+1, + maxYear: now.year + 1, maxYearMonth: 12, showMode: CalendarConstants.MODE_SHOW_MONTH_AND_WEEK); diff --git a/example/lib/main.dart b/example/lib/main.dart index 3258a09..565959e 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,6 @@ -import 'package:example/only_week_page.dart'; -import 'package:example/red_style_page.dart'; +import 'only_week_page.dart'; +import 'red_style_page.dart'; import 'package:flutter/material.dart'; - import 'blue_style_page.dart'; import 'custom_sign_page.dart'; import 'custom_style_page.dart'; @@ -113,4 +112,3 @@ class HomePage extends StatelessWidget { ); } } - diff --git a/example/pubspec.lock b/example/pubspec.lock index 1b7b8bb..681846d 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -129,7 +129,7 @@ packages: name: provider url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0+1" + version: "3.1.0+1" quiver: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index da91d24..99bb92a 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -1,5 +1,5 @@ -name: example -description: A new Flutter module. +name: example1 +description: A new Flutter project. # The following defines the version and build number for your application. # A version number is three numbers separated by dots, like 1.2.43 @@ -11,10 +11,6 @@ description: A new Flutter module. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # Read more about iOS versioning at # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# -# This version is used _only_ for the Runner app, which is used if you just do -# a `flutter run` or a `flutter make-host-app-editable`. It has no impact -# on any other native host app that you embed your Flutter project into. version: 1.0.0+1 environment: @@ -27,28 +23,26 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^0.1.2 - random_pk: any + random_pk: ^0.0.3 flutter_custom_calendar: path: ../ - -# flutter_custom_calendar: -# git: -# url: https://github.com/LXD312569496/flutter_custom_calendar.git dev_dependencies: flutter_test: sdk: flutter + # For information on the generic Dart part of this file, see the -# following page: https://www.dartlang.org/tools/pub/pubspec +# following page: https://dart.dev/tools/pub/pubspec +# The following section is specific to Flutter. flutter: + # The following line ensures that the Material Icons font is # included with your application, so that you can use the icons in # the material Icons class. uses-material-design: true - # To add Flutter specific assets to your application, add an assets section, - # like this: + # To add assets to your application, add an assets section, like this: # assets: # - images/a_dot_burr.jpeg # - images/a_dot_ham.jpeg @@ -59,9 +53,9 @@ flutter: # For details regarding adding assets from package dependencies, see # https://flutter.dev/assets-and-images/#from-packages - # To add Flutter specific custom fonts to your application, add a fonts - # section here, in this "flutter" section. Each entry in this list should - # have a "family" key with the font family name, and a "fonts" key with a + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a # list giving the asset and other descriptors for the font. For # example: # fonts: @@ -78,14 +72,3 @@ flutter: # # For details regarding fonts from package dependencies, # see https://flutter.dev/custom-fonts/#from-packages - - - # This section identifies your Flutter project as a module meant for - # embedding in a native host app. These identifiers should _not_ ordinarily - # be changed after generation - they are used to ensure that the tooling can - # maintain consistency when adding or modifying assets and plugins. - # They also do not have any bearing on your native host application's - # identifiers, which may be completely independent or the same as these. - module: - androidPackage: com.donggua.example - iosBundleIdentifier: com.donggua.example diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 747db1d..f0b07d5 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:example/main.dart'; +import 'package:example1/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { diff --git a/example/web/index.html b/example/web/index.html index f81f1ff..237c424 100644 --- a/example/web/index.html +++ b/example/web/index.html @@ -2,7 +2,7 @@ - flutter_demo + example1 diff --git a/pubspec.lock b/pubspec.lock index f59b95c..406ab5f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,20 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + archive: + dependency: transitive + description: + name: archive + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.10" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.2" async: dependency: transitive description: @@ -29,6 +43,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.14.11" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.3" flutter: dependency: "direct main" description: flutter @@ -39,6 +67,13 @@ packages: description: flutter source: sdk version: "0.0.0" + image: + dependency: transitive + description: + name: image + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.4" matcher: dependency: transitive description: @@ -59,7 +94,7 @@ packages: name: path url: "https://pub.flutter-io.cn" source: hosted - version: "1.6.2" + version: "1.6.4" pedantic: dependency: transitive description: @@ -67,20 +102,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.8.0+1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.4.0" provider: dependency: "direct main" description: name: provider url: "https://pub.flutter-io.cn" source: hosted - version: "3.0.0+1" + version: "3.1.0+1" quiver: dependency: transitive description: name: quiver url: "https://pub.flutter-io.cn" source: hosted - version: "2.0.3" + version: "2.0.5" sky_engine: dependency: transitive description: flutter @@ -113,7 +155,7 @@ packages: name: string_scanner url: "https://pub.flutter-io.cn" source: hosted - version: "1.0.4" + version: "1.0.5" term_glyph: dependency: transitive description: @@ -142,5 +184,12 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.8" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.5.0" sdks: - dart: ">=2.2.2 <3.0.0" + dart: ">=2.4.0 <3.0.0" From f812e4b84d203eb3bc6bca8dc55d1482449ed669 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 5 Nov 2019 18:37:57 +0800 Subject: [PATCH 23/25] =?UTF-8?q?fix=20bug=EF=BC=9A=E5=8A=A0=E5=85=A5?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=9A=84=E4=BB=A3=E7=A0=81=E6=9C=89=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/widget/month_view.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 2d89aa8..08815ed 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -51,8 +51,9 @@ class _MonthViewState extends State items = CacheData.getInstance().monthListCache[firstDayOfMonth]; } else { LogUtil.log(TAG: this.runtimeType, message: "缓存中无数据"); - getItems(); - CacheData.getInstance().monthListCache[firstDayOfMonth] = items; + getItems().then((_){ + CacheData.getInstance().monthListCache[firstDayOfMonth] = items; + }); } lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); @@ -68,7 +69,7 @@ class _MonthViewState extends State }); } - getItems() async { + Future getItems() async { items = await compute(initCalendarForMonthView, { 'year': widget.year, 'month': widget.month, From 21fdeb55957f501d3a1c94c7e4cfc99d4a63db91 Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 3 Dec 2019 22:57:29 +0800 Subject: [PATCH 24/25] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=91=A8=E5=88=87?= =?UTF-8?q?=E6=8D=A2=E7=9A=84=E7=9B=91=E5=90=AC=E6=96=B9=E6=B3=95=EF=BC=8C?= =?UTF-8?q?addWeekChangeListener?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/configuration.dart | 2 ++ lib/controller.dart | 10 ++++++++++ lib/widget/week_view_pager.dart | 6 +++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/configuration.dart b/lib/configuration.dart index 3bed95a..5786dd0 100644 --- a/lib/configuration.dart +++ b/lib/configuration.dart @@ -65,6 +65,8 @@ class CalendarConfiguration { ObserverList monthChangeListeners = ObserverList(); //保存多个月份监听的事件 + ObserverList weekChangeListeners = + ObserverList(); //周视图切换 /** * 下面的信息不是配置的,是根据配置信息进行计算出来的 diff --git a/lib/controller.dart b/lib/controller.dart index 2a71fb9..197ac7b 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -184,6 +184,11 @@ class CalendarController { calendarConfiguration.weekController = weekController; } + //周视图切换 + void addWeekChangeListener(OnWeekChange listener){ + this.calendarConfiguration.weekChangeListeners.add(listener); + } + //月份切换监听 void addMonthChangeListener(OnMonthChange listener) { // this.calendarConfiguration.monthChange = listener; @@ -532,6 +537,11 @@ bool defaultInRange(DateModel dateModel) { return true; } +/** + * 周视图切换 + */ +typedef void OnWeekChange(int year, int month); + /** * 月份切换事件 */ diff --git a/lib/widget/week_view_pager.dart b/lib/widget/week_view_pager.dart index 3a468c0..98b1b71 100644 --- a/lib/widget/week_view_pager.dart +++ b/lib/widget/week_view_pager.dart @@ -54,13 +54,17 @@ class _WeekViewPagerState extends State if (calendarProvider.expandStatus.value == true) { return; } + LogUtil.log( TAG: this.runtimeType, message: "WeekViewPager PageView onPageChanged,position:$position"); -// 周视图的变化 DateModel firstDayOfWeek = configuration.weekList[position]; int currentMonth = firstDayOfWeek.month; +// 周视图的变化 + configuration.weekChangeListeners.forEach((listener) { + listener(firstDayOfWeek.year, firstDayOfWeek.month); + }); if (lastMonth != currentMonth) { LogUtil.log( TAG: this.runtimeType, From ecd90edbc4002f8587823c8d44ddfa7ac1795eed Mon Sep 17 00:00:00 2001 From: LXD312569496 <450468291@qq.com> Date: Tue, 3 Dec 2019 23:49:40 +0800 Subject: [PATCH 25/25] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=9A=E5=8D=95=E9=80=89=E6=A8=A1=E5=BC=8F=E4=B8=8B=E5=A4=9A?= =?UTF-8?q?=E4=B8=AA=E6=97=A5=E6=9C=9F=E8=A2=AB=E9=80=89=E4=B8=AD=20?= =?UTF-8?q?=E5=8E=BB=E6=8E=89=E9=BB=98=E8=AE=A4dispose=E4=BC=9A=E9=94=80?= =?UTF-8?q?=E6=AF=81=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=8F=90=E4=BE=9B=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E8=AE=A9=E7=94=A8=E6=88=B7=E6=89=8B=E5=8A=A8=E9=94=80?= =?UTF-8?q?=E6=AF=81=E6=95=B0=E6=8D=AEclearData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/controller.dart | 2 ++ lib/widget/calendar_view.dart | 2 +- lib/widget/month_view.dart | 13 +++++++------ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/controller.dart b/lib/controller.dart index 197ac7b..910ce1a 100644 --- a/lib/controller.dart +++ b/lib/controller.dart @@ -502,6 +502,8 @@ class CalendarController { monthList.clear(); weekList.clear(); calendarProvider.clearData(); + calendarConfiguration.weekChangeListeners=null; + calendarConfiguration.monthChangeListeners=null; } } diff --git a/lib/widget/calendar_view.dart b/lib/widget/calendar_view.dart index 6227a64..bb016a9 100644 --- a/lib/widget/calendar_view.dart +++ b/lib/widget/calendar_view.dart @@ -69,7 +69,7 @@ class _CalendarViewWidgetState extends State { @override void dispose() { - widget.calendarController.clearData(); +// widget.calendarController.clearData(); super.dispose(); } diff --git a/lib/widget/month_view.dart b/lib/widget/month_view.dart index 08815ed..bdbafd7 100644 --- a/lib/widget/month_view.dart +++ b/lib/widget/month_view.dart @@ -162,12 +162,13 @@ class ItemContainerState extends State { dateModel = widget.dateModel; isSelected = ValueNotifier(dateModel.isSelected); - WidgetsBinding.instance.addPostFrameCallback((callback) { - if (configuration.selectMode == CalendarConstants.MODE_SINGLE_SELECT && - dateModel.isSelected) { - calendarProvider.lastClickItemState = this; - } - }); +// 先注释掉这段代码 +// WidgetsBinding.instance.addPostFrameCallback((callback) { +// if (configuration.selectMode == CalendarConstants.MODE_SINGLE_SELECT && +// dateModel.isSelected) { +// calendarProvider.lastClickItemState = this; +// } +// }); } /**