创建configuration类,将配置的信息放到这里

引入provider状态管理,避免深层嵌套传递信息
周视图和月视图,联动
增加日志输出类LogUtil,方便查看调试
增加example例子
性能优化
develop
xiaodong 5 years ago
parent b26999d210
commit 6dcf7c21a2

@ -20,7 +20,7 @@ Flutter上的一个日历控件可以定制成自己想要的样子。
## 近期修改 ## 近期修改
### [1.0.0] - 2019/9/22 ### [1.0.0] - 2019/9/22
* 重构日历的代码 * 重构日历的代码,进行性能优化
* 创建configuration类将配置的信息放到这里 * 创建configuration类将配置的信息放到这里
* 引入provider状态管理,避免深层嵌套传递信息 * 引入provider状态管理,避免深层嵌套传递信息
* 实现周视图,并实现周视图和月视图之间的联动 * 实现周视图,并实现周视图和月视图之间的联动
@ -55,8 +55,9 @@ CalendarViewWidget({@required this.calendarController, this.boxDecoration});
* boxDecoration用来配置整体的背景 * boxDecoration用来配置整体的背景
* 利用CalendarController来配置一些数据并且可以通过CalendarController进行一些操作或者事件监听比如滚动到下一个月获取当前被选中的Item等等。 * 利用CalendarController来配置一些数据并且可以通过CalendarController进行一些操作或者事件监听比如滚动到下一个月获取当前被选中的Item等等。
## 配置CalendarController
下面是CalendarController中一些支持自定义配置的属性。不配置的话会有对应的默认值。 下面是CalendarController中一些支持自定义配置的属性。不配置的话会有对应的默认值。
配置都是在controller里面进行配置的。。考虑到之前版本所以才这样搞
个人觉得配置的含义主要包括了3个方面的配置。 个人觉得配置的含义主要包括了3个方面的配置。
* 一个是显示日历所需要的相关数据, * 一个是显示日历所需要的相关数据,
@ -64,9 +65,10 @@ CalendarViewWidget({@required this.calendarController, this.boxDecoration});
* 一个是对日历的监听事件进行配置。 * 一个是对日历的监听事件进行配置。
``` ```
//构造函数 //构造函数
CalendarController( CalendarController(
{int selectMode = Constants.MODE_SINGLE_SELECT, {int selectMode = Constants.MODE_SINGLE_SELECT,
bool expandStatus = true,
DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget, DayWidgetBuilder dayWidgetBuilder = defaultCustomDayWidget,
WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget, WeekBarItemWidgetBuilder weekBarItemWidgetBuilder = defaultWeekBarWidget,
int minYear = 1971, int minYear = 1971,
@ -84,11 +86,13 @@ CalendarViewWidget({@required this.calendarController, this.boxDecoration});
Set<DateTime> selectedDateTimeList = EMPTY_SET, Set<DateTime> selectedDateTimeList = EMPTY_SET,
DateModel selectDateModel, DateModel selectDateModel,
int maxMultiSelectCount = 9999, int maxMultiSelectCount = 9999,
Map<DateTime, Object> extraDataMap = EMPTY_MAP}) double verticalSpacing = 10,
bool enableExpand = true,
Map<DateModel, Object> extraDataMap = EMPTY_MAP})
``` ```
数据方面的配置 ### 数据方面的配置
属性 | 含义 | 默认值 属性 | 含义 | 默认值
:-: | :-: | :-: :-: | :-: | :-:
@ -111,7 +115,7 @@ maxMultiSelectCount | 多选,最多选多少个| hhh
extraDataMap | 自定义额外的数据| 默认为空MapMap<DateTime, Object> extraDataMap = new Map() extraDataMap | 自定义额外的数据| 默认为空MapMap<DateTime, Object> extraDataMap = new Map()
UI绘制相关的配置 ### UI绘制相关的配置
属性 | 含义 | 默认值 属性 | 含义 | 默认值
:-: | :-: | :-: :-: | :-: | :-:
@ -119,23 +123,23 @@ weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式
dayWidgetBuilder | 创建日历item | 默认样式 dayWidgetBuilder | 创建日历item | 默认样式
事件监听的配置 ### 事件监听的配置
方法 | 含义 | 默认值 方法 | 含义 | 默认值
:-: | :-: | :-: :-: | :-: | :-:
void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 | 默认为空 void addMonthChangeListener(OnMonthChange listener) | 月份切换事件 |
void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 | 默认为空 void addOnCalendarSelectListener(OnCalendarSelect listener) | 点击选择事件 |
void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 | 默认为空 void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) | 多选超出指定范围 |
void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 | 默认为空 void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) | 多选超出限制个数 |
void addExpandChangeListener(ValueChanged<bool> expandChange)|监听日历的展开收缩状态| void addExpandChangeListener(ValueChanged<bool> expandChange)|监听日历的展开收缩状态|
### 利用controller来控制日历的切换支持配置动画 ## 利用controller来控制日历的切换支持配置动画
方法 | 含义 | 默认值 方法 | 含义 | 默认值
:-: | :-: | :-: :-: | :-: | :-:
Future<bool> previousPage()|滑动到上一个页面会自动根据当前的展开状态滑动到上一个月或者上一个星期。如果已经在第一个页面没有上一个页面就会返回false其他情况返回true| Future<bool> previousPage()|滑动到上一个页面会自动根据当前的展开状态滑动到上一个月或者上一个星期。如果已经在第一个页面没有上一个页面就会返回false其他情况返回true|
Future<bool> nextPage()|滑动到下一个页面会自动根据当前的展开状态滑动到下一个月或者下一个星期。如果已经在最后一个页面没有下一个页面就会返回false其他情况返回true| Future<bool> 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 moveToCalendar(int year, int month, int day, {bool needAnimation = false,Duration duration = const Duration(milliseconds: 500),Curve curve = Curves.ease}) | 到指定日期 |
void moveToNextYear()|切换到下一年| void moveToNextYear()|切换到下一年|
void moveToPreviousYear()|切换到上一年| void moveToPreviousYear()|切换到上一年|
void moveToNextMonth()|切换到下一个月份| void moveToNextMonth()|切换到下一个月份|
@ -143,7 +147,7 @@ void moveToPreviousMonth()|切换到上一个月份|
void toggleExpandStatus()|切换展开状态| void toggleExpandStatus()|切换展开状态|
### 利用controller来获取日历的一些数据信息 ## 利用controller来获取日历的一些数据信息
方法 | 含义 | 默认值 方法 | 含义 | 默认值
:-: | :-: | :-: :-: | :-: | :-:
@ -152,7 +156,7 @@ Set<DateModel> getMultiSelectCalendar()|获取被选中的日期,多选|
DateModel getSingleSelectCalendar()|获取被选中的日期,单选| DateModel getSingleSelectCalendar()|获取被选中的日期,单选|
### 如何自定义UI ## 如何自定义UI
包括自定义WeekBar、自定义日历Item默认使用的都是DefaultXXXWidget。 包括自定义WeekBar、自定义日历Item默认使用的都是DefaultXXXWidget。
@ -271,7 +275,7 @@ class DefaultCustomDayWidget extends BaseCustomDayWidget {
### DateModel实体类 ## DateModel实体类
日历所用的日期的实体类DateModel有下面这些属性。可以在自定义绘制DayWidget的时候根据相应的属性进行判断后绘制相应的UI。 日历所用的日期的实体类DateModel有下面这些属性。可以在自定义绘制DayWidget的时候根据相应的属性进行判断后绘制相应的UI。
属性|含义|类型|默认值 属性|含义|类型|默认值
@ -286,12 +290,12 @@ lunarString|农历字符串|String|
solarTerm|24节气|String| solarTerm|24节气|String|
gregorianFestival|gregorianFestival|String| gregorianFestival|gregorianFestival|String|
traditionFestival|传统农历节日|String| traditionFestival|传统农历节日|String|
isCurrentDay|是否是今天|bool| isCurrentDay|是否是今天|bool|false
isLeapYear|是否是闰年|bool| isLeapYear|是否是闰年|bool|false
isWeekend|是否是周末|bool| isWeekend|是否是周末|bool|false
isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false isInRange|是否在范围内,比如可以实现在某个范围外,设置置灰的功能|bool|false
isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false isSelected|是否被选中,用来实现一些标记或者选择功能|bool|false
extraData|自定义的额外数据|Object extraData|自定义的额外数据|Object|默认为空
方法|含义| 方法|含义|

@ -23,8 +23,12 @@ class _DefaultStylePageState extends State<DefaultStylePage> {
@override @override
void initState() { void initState() {
DateTime now = DateTime.now();
controller = new CalendarController( controller = new CalendarController(
minYear: 2019, minYearMonth: 8, maxYear: 2019, maxYearMonth: 9); minYear: now.year,
minYearMonth: now.month - 2,
maxYear: now.year,
maxYearMonth: now.month + 1);
controller.addMonthChangeListener( controller.addMonthChangeListener(
(year, month) { (year, month) {

@ -1,17 +1,23 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'custom_sign_page.dart'; import 'custom_sign_page.dart';
import 'custom_style_page.dart'; import 'custom_style_page.dart';
import 'default_style_page.dart'; import 'default_style_page.dart';
import 'multi_select_style_page.dart'; import 'multi_select_style_page.dart';
import 'progress_style_page.dart'; import 'progress_style_page.dart';
void main() => runApp(MyApp()); void main(){
// debugProfileBuildsEnabled=true;
// debugProfilePaintsEnabled=true;
runApp(MyApp());
}
class MyApp extends StatelessWidget { class MyApp extends StatelessWidget {
// This widget is the root of your application. // This widget is the root of your application.
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
// checkerboardOffscreenLayers: true, // 使saveLayer
routes: <String, WidgetBuilder>{ routes: <String, WidgetBuilder>{
"/default": (context) => DefaultStylePage( "/default": (context) => DefaultStylePage(
title: "默认风格+单选", title: "默认风格+单选",

@ -1,6 +1,20 @@
# Generated by pub # Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile # See https://dart.dev/tools/pub/glossary#lockfile
packages: 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: async:
dependency: transitive dependency: transitive
description: description:
@ -29,6 +43,20 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.14.11" 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"
cupertino_icons: cupertino_icons:
dependency: "direct main" dependency: "direct main"
description: description:
@ -53,6 +81,13 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
image:
dependency: transitive
description:
name: image
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -81,6 +116,13 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.8.0+1" version: "1.8.0+1"
petitparser:
dependency: transitive
description:
name: petitparser
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.0"
provider: provider:
dependency: transitive dependency: transitive
description: description:
@ -163,5 +205,12 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.0.8" version: "2.0.8"
xml:
dependency: transitive
description:
name: xml
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.5.0"
sdks: sdks:
dart: ">=2.2.2 <3.0.0" dart: ">=2.4.0 <3.0.0"

@ -0,0 +1,26 @@
import 'package:flutter_custom_calendar/model/date_model.dart';
/**
*
*/
class CacheData {
//
CacheData._();
static CacheData _instance;
static CacheData get instance => _instance;
Map<DateModel, List<DateModel>> monthListCache = Map();
Map<DateModel, List<DateModel>> weekListCache = Map();
static CacheData getInstance() {
if (_instance == null) {
_instance = new CacheData._();
}
return _instance;
}
}

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.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:flutter_custom_calendar/widget/month_view.dart';
/** /**
@ -12,8 +13,17 @@ import 'package:flutter_custom_calendar/widget/month_view.dart';
class CalendarProvider extends ChangeNotifier { class CalendarProvider extends ChangeNotifier {
Set<DateModel> selectedDateList = new Set(); //, Set<DateModel> selectedDateList = new Set(); //,
DateModel _selectDateModel; // DateModel _selectDateModel; //
DateModel lastClickDateModel; // ItemContainerState lastClickItemState;
MultiSelectItemContainerState lastClickItemState;
DateModel _lastClickDateModel;
DateModel get lastClickDateModel =>
_lastClickDateModel; //
set lastClickDateModel(DateModel value) {
_lastClickDateModel = value;
print("lastClickDateModel:$lastClickDateModel");
}
DateModel get selectDateModel => _selectDateModel; DateModel get selectDateModel => _selectDateModel;
@ -22,7 +32,49 @@ class CalendarProvider extends ChangeNotifier {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: "selectDateModel change:${selectDateModel}"); message: "selectDateModel change:${selectDateModel}");
notifyListeners(); // notifyListeners();
}
//lastClickDateModelindex
int get weekPageIndex {
//index
DateModel dateModel = lastClickDateModel;
DateTime firstWeek = calendarConfiguration.weekList[0].getDateTime();
int index = 0;
for (int i = 0; i < calendarConfiguration.weekList.length; i++) {
DateTime nextWeek = firstWeek.add(Duration(days: 7));
if (dateModel.getDateTime().isBefore(nextWeek)) {
index = i;
break;
} else {
firstWeek = nextWeek;
index++;
}
}
print("lastClickDateModel:$lastClickDateModel,weekPageIndex:$index");
return index;
}
//lastClickDateModelindex
int get monthPageIndex {
//index
DateModel dateModel = lastClickDateModel;
int index = 0;
for (int i = 0; i < calendarConfiguration.monthList.length - 1; i++) {
DateTime preMonth = calendarConfiguration.monthList[i].getDateTime();
DateTime nextMonth = calendarConfiguration.monthList[i + 1].getDateTime();
if (!dateModel.getDateTime().isBefore(preMonth) &&
!dateModel.getDateTime().isAfter(nextMonth)) {
index = i;
break;
} else {
index++;
}
}
print("lastClickDateModel:$lastClickDateModel,monthPageIndex:$index");
return index + 1;
} }
ValueNotifier<bool> expandStatus = ValueNotifier(true); // ValueNotifier<bool> expandStatus = ValueNotifier(true); //
@ -43,7 +95,15 @@ class CalendarProvider extends ChangeNotifier {
//lastClickDateModelitem //lastClickDateModelitem
this.lastClickDateModel = selectDateModel != null this.lastClickDateModel = selectDateModel != null
? selectDateModel ? selectDateModel
: DateModel.fromDateTime(DateTime.now()); : DateModel.fromDateTime(DateTime.now())
..day = 15;
// expandStatus.addListener(() {
// print("1111");
// if (expandStatus.value == false) {
// calendarConfiguration.weekController.jumpToPage(weekPageIndex);
// }
// });
} }
//退 //退

@ -9,8 +9,11 @@ class CalendarConfiguration {
//,MODE_SINGLE_SELECTMODE_MULTI_SELECT //,MODE_SINGLE_SELECTMODE_MULTI_SELECT
int selectMode; int selectMode;
//
int showMode;
bool defaultExpandStatus; //,truefalse bool defaultExpandStatus; //,truefalse
bool enableExpand; // bool enableExpand; //,truefalse
// //
int minYear; int minYear;
@ -42,6 +45,7 @@ class CalendarConfiguration {
*/ */
double verticalSpacing; //item10 double verticalSpacing; //item10
BoxDecoration boxDecoration; // BoxDecoration boxDecoration; //
double itemSize; ///7
// //
DayWidgetBuilder dayWidgetBuilder; //item DayWidgetBuilder dayWidgetBuilder; //item
@ -61,7 +65,7 @@ class CalendarConfiguration {
*/ */
List<DateModel> monthList = new List(); //list List<DateModel> monthList = new List(); //list
List<DateModel> weekList = new List(); //list List<DateModel> weekList = new List(); //list
PageController pageController; //controller PageController monthController; //controller
PageController weekController; //controller PageController weekController; //controller
CalendarConfiguration( CalendarConfiguration(
@ -83,9 +87,10 @@ class CalendarConfiguration {
this.extraDataMap, this.extraDataMap,
this.monthList, this.monthList,
this.weekList, this.weekList,
this.pageController, this.monthController,
this.weekController, this.weekController,
this.verticalSpacing, this.verticalSpacing,
this.itemSize,
this.enableExpand, this.enableExpand,
bool defaultExpandStatus}) { bool defaultExpandStatus}) {
this.defaultExpandStatus = defaultExpandStatus; this.defaultExpandStatus = defaultExpandStatus;
@ -93,6 +98,6 @@ class CalendarConfiguration {
@override @override
String toString() { String toString() {
return 'CalendarConfiguration{selectMode: $selectMode, expandStatus: $defaultExpandStatus, minYear: $minYear, maxYear: $maxYear, minYearMonth: $minYearMonth, maxYearMonth: $maxYearMonth, nowYear: $nowYear, nowMonth: $nowMonth, minSelectYear: $minSelectYear, minSelectMonth: $minSelectMonth, minSelectDay: $minSelectDay, maxSelectYear: $maxSelectYear, maxSelectMonth: $maxSelectMonth, maxSelectDay: $maxSelectDay, defaultSelectedDateList: $defaultSelectedDateList, maxMultiSelectCount: $maxMultiSelectCount, extraDataMap: $extraDataMap, monthList: $monthList, weekList: $weekList, pageController: $pageController, weekController: $weekController}'; return 'CalendarConfiguration{selectMode: $selectMode, expandStatus: $defaultExpandStatus, minYear: $minYear, maxYear: $maxYear, minYearMonth: $minYearMonth, maxYearMonth: $maxYearMonth, nowYear: $nowYear, nowMonth: $nowMonth, minSelectYear: $minSelectYear, minSelectMonth: $minSelectMonth, minSelectDay: $minSelectDay, maxSelectYear: $maxSelectYear, maxSelectMonth: $maxSelectMonth, maxSelectDay: $maxSelectDay, defaultSelectedDateList: $defaultSelectedDateList, maxMultiSelectCount: $maxMultiSelectCount, extraDataMap: $extraDataMap, monthList: $monthList, weekList: $weekList, monthController: $monthController, weekController: $weekController}';
} }
} }

@ -84,7 +84,7 @@ class CalendarController {
} }
//pageController,initialPage //pageController,initialPage
int initialPage; int initialPage = 0;
int nowMonthIndex = 0; int nowMonthIndex = 0;
monthList.clear(); monthList.clear();
for (int i = minYear; i <= maxYear; i++) { for (int i = minYear; i <= maxYear; i++) {
@ -111,7 +111,8 @@ class CalendarController {
nowMonthIndex++; nowMonthIndex++;
} }
} }
this.monthController = new PageController(initialPage: initialPage); this.monthController =
new PageController(initialPage: initialPage, keepPage: true);
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: "start:${DateModel.fromDateTime(DateTime( message: "start:${DateModel.fromDateTime(DateTime(
@ -153,7 +154,7 @@ class CalendarController {
calendarConfiguration.monthList = monthList; calendarConfiguration.monthList = monthList;
calendarConfiguration.weekList = weekList; calendarConfiguration.weekList = weekList;
calendarConfiguration.pageController = monthController; calendarConfiguration.monthController = monthController;
calendarConfiguration.weekController = weekController; calendarConfiguration.weekController = weekController;
calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder; calendarConfiguration.dayWidgetBuilder = dayWidgetBuilder;
calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder; calendarConfiguration.weekBarItemWidgetBuilder = weekBarItemWidgetBuilder;
@ -200,22 +201,31 @@ class CalendarController {
Future<bool> previousPage() async { Future<bool> previousPage() async {
if (calendarProvider.expandStatus.value == true) { if (calendarProvider.expandStatus.value == true) {
// //
int currentIndex = monthController.page.toInt(); int currentIndex =
calendarProvider.calendarConfiguration.monthController.page.toInt();
if (currentIndex == 0) { if (currentIndex == 0) {
return false; return false;
} else { } else {
monthController.previousPage( calendarProvider.calendarConfiguration.monthController
duration: DEFAULT_DURATION, curve: Curves.ease); .previousPage(duration: DEFAULT_DURATION, curve: Curves.ease);
calendarProvider.calendarConfiguration.monthChange(
monthList[currentIndex].year, monthList[currentIndex].month);
DateModel temp = new DateModel();
temp.year = monthList[currentIndex].year;
temp.month = monthList[currentIndex].month;
temp.day = monthList[currentIndex].day + 14;
calendarProvider.lastClickDateModel = temp;
return true; return true;
} }
} else { } else {
// //
int currentIndex = weekController.page.toInt(); int currentIndex =
calendarProvider.calendarConfiguration.weekController.page.toInt();
if (currentIndex == 0) { if (currentIndex == 0) {
return false; return false;
} else { } else {
weekController.previousPage( calendarProvider.calendarConfiguration.weekController
duration: DEFAULT_DURATION, curve: Curves.ease); .previousPage(duration: DEFAULT_DURATION, curve: Curves.ease);
return true; return true;
} }
} }
@ -229,21 +239,31 @@ class CalendarController {
Future<bool> nextPage() async { Future<bool> nextPage() async {
if (calendarProvider.expandStatus.value == true) { if (calendarProvider.expandStatus.value == true) {
// //
int currentIndex = monthController.page.toInt(); int currentIndex =
calendarProvider.calendarConfiguration.monthController.page.toInt();
if (monthList.length - 1 == currentIndex) { if (monthList.length - 1 == currentIndex) {
return false; return false;
} else { } else {
monthController.nextPage( calendarProvider.calendarConfiguration.monthController
duration: DEFAULT_DURATION, curve: Curves.ease); .nextPage(duration: DEFAULT_DURATION, curve: Curves.ease);
calendarProvider.calendarConfiguration.monthChange(
monthList[currentIndex].year, monthList[currentIndex].month);
DateModel temp = new DateModel();
temp.year = monthList[currentIndex].year;
temp.month = monthList[currentIndex].month;
temp.day = monthList[currentIndex].day + 14;
calendarProvider.lastClickDateModel = temp;
return true; return true;
} }
} else { } else {
// //
int currentIndex = weekController.page.toInt(); int currentIndex =
calendarProvider.calendarConfiguration.weekController.page.toInt();
if (weekList.length - 1 == currentIndex) { if (weekList.length - 1 == currentIndex) {
return false; return false;
} else { } else {
weekController.nextPage(duration: DEFAULT_DURATION, curve: Curves.ease); calendarProvider.calendarConfiguration.weekController
.nextPage(duration: DEFAULT_DURATION, curve: Curves.ease);
return true; return true;
} }
} }
@ -261,14 +281,16 @@ class CalendarController {
if (targetPage == -1) { if (targetPage == -1) {
return; return;
} }
if (monthController.hasClients == false) { if (calendarProvider.calendarConfiguration.monthController.hasClients ==
false) {
return; return;
} }
if (needAnimation) { if (needAnimation) {
monthController.animateToPage(targetPage, calendarProvider.calendarConfiguration.monthController
duration: duration, curve: curve); .animateToPage(targetPage, duration: duration, curve: curve);
} else { } else {
monthController.jumpToPage(targetPage); calendarProvider.calendarConfiguration.monthController
.jumpToPage(targetPage);
} }
} else { } else {
DateModel dateModel = DateModel.fromDateTime(DateTime(year, month, 1)); DateModel dateModel = DateModel.fromDateTime(DateTime(year, month, 1));
@ -282,14 +304,16 @@ class CalendarController {
return; return;
} }
} }
if (weekController.hasClients == false) { if (calendarProvider.calendarConfiguration.weekController.hasClients ==
false) {
return; return;
} }
if (needAnimation) { if (needAnimation) {
weekController.animateToPage(targetPage, calendarProvider.calendarConfiguration.weekController
duration: duration, curve: curve); .animateToPage(targetPage, duration: duration, curve: curve);
} else { } else {
weekController.jumpToPage(targetPage); calendarProvider.calendarConfiguration.weekController
.jumpToPage(targetPage);
} }
} }
} }
@ -299,8 +323,11 @@ class CalendarController {
{bool needAnimation = false, {bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500), Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) { Curve curve = Curves.ease}) {
DateTime targetDateTime = DateTime targetDateTime = monthList[calendarProvider
monthList[monthController.page.toInt() + 12].getDateTime(); .calendarConfiguration.monthController.page
.toInt() +
12]
.getDateTime();
moveToCalendar( moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day, targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve); needAnimation: needAnimation, duration: duration, curve: curve);
@ -311,8 +338,11 @@ class CalendarController {
{bool needAnimation = false, {bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500), Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) { Curve curve = Curves.ease}) {
DateTime targetDateTime = DateTime targetDateTime = monthList[calendarProvider
monthList[monthController.page.toInt() - 12].getDateTime(); .calendarConfiguration.monthController.page
.toInt() -
12]
.getDateTime();
moveToCalendar( moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day, targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve); needAnimation: needAnimation, duration: duration, curve: curve);
@ -325,22 +355,33 @@ class CalendarController {
Curve curve = Curves.ease}) { Curve curve = Curves.ease}) {
// indexweekController // indexweekController
if (calendarProvider.expandStatus.value == false) { if (calendarProvider.expandStatus.value == false) {
int currentMonth = weekList[weekController.page.toInt()].month; int currentMonth = weekList[calendarProvider
for (int i = weekController.page.toInt(); i < weekList.length; i++) { .calendarConfiguration.weekController.page
.toInt()]
.month;
for (int i = calendarProvider.calendarConfiguration.weekController.page
.toInt();
i < weekList.length;
i++) {
if (weekList[i].month != currentMonth) { if (weekList[i].month != currentMonth) {
weekController.jumpToPage(i); calendarProvider.calendarConfiguration.weekController.jumpToPage(i);
break; break;
} }
} }
return; return;
} }
if ((monthController.page.toInt() + 1) >= monthList.length) { if ((calendarProvider.calendarConfiguration.monthController.page.toInt() +
1) >=
monthList.length) {
LogUtil.log(TAG: this.runtimeType, message: "moveToNextMonth当前是最后一个月份"); LogUtil.log(TAG: this.runtimeType, message: "moveToNextMonth当前是最后一个月份");
return; return;
} }
DateTime targetDateTime = DateTime targetDateTime = monthList[calendarProvider
monthList[monthController.page.toInt() + 1].getDateTime(); .calendarConfiguration.monthController.page
.toInt() +
1]
.getDateTime();
moveToCalendar( moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day, targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve); needAnimation: needAnimation, duration: duration, curve: curve);
@ -354,25 +395,32 @@ class CalendarController {
// indexweekController // indexweekController
if (calendarProvider.expandStatus.value == false) { if (calendarProvider.expandStatus.value == false) {
int currentMonth = weekList[weekController.page.toInt()].month; int currentMonth = weekList[weekController.page.toInt()].month;
for (int i = weekController.page.toInt(); i >= 0; i--) { for (int i = calendarProvider.calendarConfiguration.weekController.page
.toInt();
i >= 0;
i--) {
if (weekList[i].month != currentMonth && if (weekList[i].month != currentMonth &&
weekList[i].isAfter(DateModel.fromDateTime(DateTime( weekList[i].isAfter(DateModel.fromDateTime(DateTime(
calendarConfiguration.minYear, calendarConfiguration.minYear,
calendarConfiguration.minYearMonth)))) { calendarConfiguration.minYearMonth)))) {
weekController.jumpToPage(i); calendarProvider.calendarConfiguration.weekController.jumpToPage(i);
break; break;
} }
} }
return; return;
} }
if ((monthController.page.toInt()) == 0) { if ((calendarProvider.calendarConfiguration.monthController.page.toInt()) ==
0) {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, message: "moveToPreviousMonth当前是第一个月份"); TAG: this.runtimeType, message: "moveToPreviousMonth当前是第一个月份");
return; return;
} }
DateTime targetDateTime = DateTime targetDateTime = monthList[calendarProvider
monthList[monthController.page.toInt() - 1].getDateTime(); .calendarConfiguration.monthController.page
.toInt() -
1]
.getDateTime();
moveToCalendar( moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day, targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve); needAnimation: needAnimation, duration: duration, curve: curve);
@ -398,7 +446,7 @@ class CalendarController {
* weekBar * weekBar
*/ */
Widget defaultWeekBarWidget() { Widget defaultWeekBarWidget() {
return DefaultWeekBar(); return const DefaultWeekBar();
} }
/** /**

@ -11,6 +11,13 @@ class DateModel {
List<int> lunar = List(3); List<int> lunar = List(3);
// List<int> get lunar {
// if (lunar?.isNotEmpty == false) {
// return lunar;
// }
//// return LunarUtil.solarToLunar(year, month, day);
// }
// //
String get lunarString { String get lunarString {
if (solarTerm.isNotEmpty) { if (solarTerm.isNotEmpty) {

@ -1,3 +1,4 @@
import 'dart:developer';
import 'dart:math'; import 'dart:math';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
@ -114,6 +115,7 @@ class DateUtil {
{DateModel minSelectDate, {DateModel minSelectDate,
DateModel maxSelectDate, DateModel maxSelectDate,
Map<DateModel, Object> extraDataMap}) { Map<DateModel, Object> extraDataMap}) {
print('initCalendarForMonthView start');
weekStart = DateTime.monday; weekStart = DateTime.monday;
// //
int mPreDiff = getIndexOfFirstDayInMonth(new DateTime(year, month)); int mPreDiff = getIndexOfFirstDayInMonth(new DateTime(year, month));
@ -125,6 +127,7 @@ class DateUtil {
message: message:
"initCalendarForMonthView:$year$month月,有$monthDayCount天,第一天的index为${mPreDiff}"); "initCalendarForMonthView:$year$month月,有$monthDayCount天,第一天的index为${mPreDiff}");
List<DateModel> result = new List(); List<DateModel> result = new List();
int size = 42; int size = 42;
@ -162,7 +165,7 @@ class DateUtil {
dateModel.isInRange = false; dateModel.isInRange = false;
} }
//model //model
if (extraDataMap != null && extraDataMap.isNotEmpty) { if (extraDataMap?.isNotEmpty == true) {
if (extraDataMap.containsKey(dateModel)) { if (extraDataMap.containsKey(dateModel)) {
dateModel.extraData = extraDataMap[dateModel]; dateModel.extraData = extraDataMap[dateModel];
} }
@ -171,6 +174,8 @@ class DateUtil {
result.add(dateModel); result.add(dateModel);
} }
print('initCalendarForMonthView end');
return result; return result;
} }
@ -200,7 +205,6 @@ class DateUtil {
{DateModel minSelectDate, {DateModel minSelectDate,
DateModel maxSelectDate, DateModel maxSelectDate,
Map<DateModel, Object> extraDataMap}) { Map<DateModel, Object> extraDataMap}) {
LogUtil.log(TAG: "DateUtil", message: "initCalendarForWeekView");
List<DateModel> items = List(); List<DateModel> items = List();
int weekDay = currentDate.weekday; int weekDay = currentDate.weekday;
@ -226,7 +230,7 @@ class DateUtil {
} }
//model //model
if (extraDataMap != null && extraDataMap.isNotEmpty) { if (extraDataMap?.isNotEmpty == true) {
if (extraDataMap.containsKey(dateModel)) { if (extraDataMap.containsKey(dateModel)) {
dateModel.extraData = extraDataMap[dateModel]; dateModel.extraData = extraDataMap[dateModel];
} }

@ -6,9 +6,9 @@ import 'package:flutter_custom_calendar/model/date_model.dart';
* canvasitem * canvasitem
*/ */
abstract class BaseCustomDayWidget extends StatelessWidget { abstract class BaseCustomDayWidget extends StatelessWidget {
DateModel dateModel; final DateModel dateModel;
BaseCustomDayWidget( const BaseCustomDayWidget(
this.dateModel, this.dateModel,
); );

@ -1,8 +1,10 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/LogUtil.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'; import 'package:flutter_custom_calendar/widget/month_view_pager.dart';
import 'package:flutter_custom_calendar/widget/week_view_pager.dart'; import 'package:flutter_custom_calendar/widget/week_view_pager.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -66,16 +68,41 @@ class CalendarContainerState extends State<CalendarContainer>
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
var state = CrossFadeState.showFirst;
List<Widget> widgets;
int index = 0;
@override @override
void initState() { void initState() {
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
expand = calendarProvider.expandStatus.value; expand = calendarProvider.expandStatus.value;
widgets = [
const MonthViewPager(),
const WeekViewPager(),
];
// //
if (calendarProvider.calendarConfiguration.enableExpand == true) { if (calendarProvider.calendarConfiguration.enableExpand == true) {
calendarProvider.expandStatus.addListener(() { calendarProvider.expandStatus.addListener(() {
setState(() { setState(() {
expand = !expand; expand = calendarProvider.expandStatus.value;
state = (state == CrossFadeState.showSecond
? CrossFadeState.showFirst
: CrossFadeState.showSecond);
if (expand) {
index = 0;
//
calendarProvider.calendarConfiguration.weekController
.jumpToPage(calendarProvider.monthPageIndex);
} else {
index = 1;
//
calendarProvider.calendarConfiguration.weekController
.jumpToPage(calendarProvider.weekPageIndex);
}
}); });
}); });
} }
@ -90,28 +117,60 @@ class CalendarContainerState extends State<CalendarContainer>
Widget build(BuildContext context) { Widget build(BuildContext context) {
LogUtil.log(TAG: this.runtimeType, message: "CalendarContainerState build"); 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. //,,:a horizontal viewport was given an unlimited amount of I/flutter ( 6759): vertical space in which to expand.
itemHeight = MediaQuery.of(context).size.width / 7; itemHeight = calendarProvider.calendarConfiguration.itemSize ??
MediaQuery.of(context).size.width / 7;
totalHeight = itemHeight * 6 + 10 * (6 - 1); totalHeight = itemHeight * 6 + 10 * (6 - 1);
// return Container(
// child: new Column(
// children: <Widget>[
// /**
// * constsetStateview
// */
// calendarProvider.calendarConfiguration.weekBarItemWidgetBuilder(),
// AnimatedContainer(
// duration: Duration(milliseconds: 200),
// width: itemHeight * 7,
// height: expand ? totalHeight : itemHeight,
// child: expand
// ? Container(
// height: totalHeight,
// child: MonthViewPager(),
// )
// : Container(
// height: itemHeight,
// child: WeekViewPager(),
// ),
// ),
// ],
// ),
// );
// return Container(
// child: AnimatedCrossFade(
// firstChild: Container(height: totalHeight, child: MonthViewPager()),
// secondChild: Container(height: itemHeight, child: WeekViewPager()),
// crossFadeState: state,
// duration: Duration(milliseconds: 500)),
// );
return Container( return Container(
width: itemHeight * 7,
child: new Column( child: new Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
/** /**
* constsetStateview * constsetStateview
*/ */
calendarProvider.calendarConfiguration.weekBarItemWidgetBuilder(), calendarProvider.calendarConfiguration.weekBarItemWidgetBuilder(),
AnimatedContainer( AnimatedContainer(
duration: Duration(milliseconds: 200), duration: Duration(milliseconds: 500),
height: expand ? totalHeight : itemHeight, height: expand ? totalHeight : itemHeight,
child: expand child: IndexedStack(
? Container( // overflow: Overflow.visible,
height: totalHeight, index: index,
child: MonthViewPager(), children: widgets,
) )),
: Container(
height: itemHeight,
child: WeekViewPager(),
),
),
], ],
), ),
); );

@ -8,7 +8,7 @@ import 'package:flutter_custom_calendar/style/style.dart';
*/ */
class DefaultCustomDayWidget extends BaseCustomDayWidget { class DefaultCustomDayWidget extends BaseCustomDayWidget {
DefaultCustomDayWidget(DateModel dateModel) : super(dateModel); const DefaultCustomDayWidget(DateModel dateModel) : super(dateModel);
@override @override
void drawNormal(DateModel dateModel, Canvas canvas, Size size) { void drawNormal(DateModel dateModel, Canvas canvas, Size size) {

@ -1,4 +1,8 @@
import 'dart:developer';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/cache_data.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/constants/constants.dart'; import 'package:flutter_custom_calendar/constants/constants.dart';
@ -15,25 +19,21 @@ class MonthView extends StatefulWidget {
final int month; final int month;
final int day; final int day;
final DateModel minSelectDate; final CalendarConfiguration configuration;
final DateModel maxSelectDate;
final Map<DateModel, Object> extraDataMap; //
const MonthView({ const MonthView({
@required this.year, @required this.year,
@required this.month, @required this.month,
this.day, this.day,
this.minSelectDate, this.configuration,
this.maxSelectDate,
this.extraDataMap,
}); });
@override @override
_MonthViewState createState() => _MonthViewState(); _MonthViewState createState() => _MonthViewState();
} }
class _MonthViewState extends State<MonthView> { class _MonthViewState extends State<MonthView>
with AutomaticKeepAliveClientMixin {
List<DateModel> items; List<DateModel> items;
int lineCount; int lineCount;
@ -42,21 +42,46 @@ class _MonthViewState extends State<MonthView> {
double totalHeight; double totalHeight;
double mainSpacing = 10; double mainSpacing = 10;
DateModel minSelectDate;
DateModel maxSelectDate;
Map<DateModel, Object> extraDataMap; //
@override @override
void initState() { void initState() {
super.initState(); super.initState();
items = DateUtil.initCalendarForMonthView( minSelectDate = DateModel.fromDateTime(DateTime(
widget.year, widget.month, DateTime.now(), DateTime.sunday, widget.configuration.minSelectYear,
minSelectDate: widget.minSelectDate, widget.configuration.minSelectMonth,
maxSelectDate: widget.maxSelectDate, widget.configuration.minSelectDay));
extraDataMap: widget.extraDataMap); maxSelectDate = DateModel.fromDateTime(DateTime(
widget.configuration.maxSelectYear,
widget.configuration.maxSelectMonth,
widget.configuration.maxSelectDay));
extraDataMap = widget.configuration.extraDataMap;
DateModel firstDayOfMonth =
DateModel.fromDateTime(DateTime(widget.year, widget.month, 1));
if (CacheData.getInstance().monthListCache[firstDayOfMonth]?.isNotEmpty ==
true) {
LogUtil.log(TAG: this.runtimeType, message: "缓存中有数据");
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);
CacheData.getInstance().monthListCache[firstDayOfMonth] = items;
}
lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month); lineCount = DateUtil.getMonthViewLineCount(widget.year, widget.month);
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context);
LogUtil.log(TAG: this.runtimeType, message: "_MonthViewState build"); LogUtil.log(TAG: this.runtimeType, message: "_MonthViewState build");
itemHeight = MediaQuery.of(context).size.width / 7; itemHeight = MediaQuery.of(context).size.width / 7;
totalHeight = itemHeight * lineCount + mainSpacing * (lineCount - 1); totalHeight = itemHeight * lineCount + mainSpacing * (lineCount - 1);
@ -92,99 +117,109 @@ class _MonthViewState extends State<MonthView> {
} }
} }
return MultiSelectItemContainer( return ItemContainer(
dateModel: dateModel, dateModel: dateModel,
configuration: configuration, // configuration: configuration,
calendarProvider: calendarProvider, // calendarProvider: calendarProvider,
); );
}); });
} }
@override
bool get wantKeepAlive => true;
} }
/** /**
* itemitem * itemitem
*/ */
class MultiSelectItemContainer extends StatefulWidget { class ItemContainer extends StatefulWidget {
final DateModel dateModel; final DateModel dateModel;
CalendarConfiguration configuration;
CalendarProvider calendarProvider;
MultiSelectItemContainer( // CalendarConfiguration configuration;
{Key key, this.dateModel, this.configuration, this.calendarProvider}) // CalendarProvider calendarProvider;
: super(key: key);
const ItemContainer({
Key key,
this.dateModel,
}) : super(key: key);
@override @override
MultiSelectItemContainerState createState() => ItemContainerState createState() => ItemContainerState();
MultiSelectItemContainerState();
} }
class MultiSelectItemContainerState extends State<MultiSelectItemContainer> { class ItemContainerState extends State<ItemContainer> {
DateModel dateModel; DateModel dateModel;
CalendarConfiguration configuration; CalendarConfiguration configuration;
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
ValueNotifier<bool> isSelected;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
dateModel = widget.dateModel; dateModel = widget.dateModel;
configuration = widget.configuration; isSelected = ValueNotifier(dateModel.isSelected);
calendarProvider = widget.calendarProvider;
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// LogUtil.log( // LogUtil.log(TAG: this.runtimeType,message: "ItemContainerState build");
// TAG: this.runtimeType, calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
// message: "_ItemContainerState build ${dateModel}"); configuration = calendarProvider.calendarConfiguration;
return Container(
child: GestureDetector( return GestureDetector(
//item //item
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
onTap: () { onTap: () {
LogUtil.log( LogUtil.log(
TAG: this.runtimeType, TAG: this.runtimeType,
message: "GestureDetector onTap: $dateModel}"); message: "GestureDetector onTap: $dateModel}");
// //
if (!dateModel.isInRange) { if (!dateModel.isInRange) {
// //
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
configuration.multiSelectOutOfRange(); configuration.multiSelectOutOfRange();
}
return;
} }
return;
}
calendarProvider.lastClickDateModel = dateModel; calendarProvider.lastClickDateModel = dateModel;
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
//
if (calendarProvider.selectedDateList.length ==
configuration.maxMultiSelectCount) {
configuration.multiSelectOutOfSize();
return;
}
configuration.calendarSelect(dateModel); if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
if (calendarProvider.selectedDateList.contains(dateModel)) { //
calendarProvider.selectedDateList.remove(dateModel); if (calendarProvider.selectedDateList.length ==
} else { configuration.maxMultiSelectCount) {
calendarProvider.selectedDateList.add(dateModel); configuration.multiSelectOutOfSize();
} return;
}
// configuration.calendarSelect(dateModel);
calendarProvider.selectDateModel = dateModel; if (calendarProvider.selectedDateList.contains(dateModel)) {
calendarProvider.selectedDateList.remove(dateModel);
} else { } else {
calendarProvider.selectDateModel = dateModel; calendarProvider.selectedDateList.add(dateModel);
configuration.calendarSelect(dateModel);
calendarProvider.lastClickItemState?.refreshItem();
calendarProvider.lastClickItemState = this;
} }
refreshItem(); //
}, calendarProvider.selectDateModel = dateModel;
child: configuration.dayWidgetBuilder(dateModel), } else {
), calendarProvider.selectDateModel = dateModel;
configuration.calendarSelect(dateModel);
//item
calendarProvider.lastClickItemState?.refreshItem();
calendarProvider.lastClickItemState = this;
}
refreshItem();
},
child: configuration.dayWidgetBuilder(dateModel),
// child: ValueListenableBuilder(
// valueListenable: isSelected,
// builder: (BuildContext context, bool value, Widget child) {
// return configuration.dayWidgetBuilder(dateModel);
// }),
); );
} }
@ -198,9 +233,10 @@ class MultiSelectItemContainerState extends State<MultiSelectItemContainer> {
The following assertion was thrown while handling a gesture: The following assertion was thrown while handling a gesture:
setState() called after dispose() setState() called after dispose()
*/ */
if(mounted){ if (mounted) {
setState(() { setState(() {
dateModel.isSelected = !dateModel.isSelected; dateModel.isSelected = !dateModel.isSelected;
// isSelected.value = !isSelected.value;
}); });
} }
} }

@ -2,12 +2,13 @@ import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/calendar_provider.dart'; import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/model/date_model.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/utils/date_util.dart';
import 'package:flutter_custom_calendar/widget/month_view.dart'; import 'package:flutter_custom_calendar/widget/month_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class MonthViewPager extends StatefulWidget { class MonthViewPager extends StatefulWidget {
MonthViewPager(); const MonthViewPager({Key key}) : super(key: key);
@override @override
_MonthViewPagerState createState() => _MonthViewPagerState(); _MonthViewPagerState createState() => _MonthViewPagerState();
@ -18,37 +19,44 @@ class _MonthViewPagerState extends State<MonthViewPager> {
var totalHeight; var totalHeight;
// PageController newPageController;
@override @override
void initState() { void initState() {
LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager initState");
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
//index // //index
DateModel dateModel = calendarProvider.lastClickDateModel; // DateModel dateModel = calendarProvider.lastClickDateModel;
List<DateModel> monthList = // List<DateModel> monthList =
calendarProvider.calendarConfiguration.monthList; // calendarProvider.calendarConfiguration.monthList;
int index = 0; // int index = 0;
for (int i = 0; i < monthList.length; i++) { // for (int i = 0; i < monthList.length; i++) {
DateModel firstDayOfMonth = monthList[i]; // DateModel firstDayOfMonth = monthList[i];
DateModel lastDayOfMonth = DateModel.fromDateTime(firstDayOfMonth // DateModel lastDayOfMonth = DateModel.fromDateTime(firstDayOfMonth
.getDateTime() // .getDateTime()
.add(Duration( // .add(Duration(
days: DateUtil.getMonthDaysCount( // days: DateUtil.getMonthDaysCount(
firstDayOfMonth.year, firstDayOfMonth.month)))); // firstDayOfMonth.year, firstDayOfMonth.month))));
//
// if ((dateModel.isAfter(firstDayOfMonth) ||
// dateModel.isSameWith(firstDayOfMonth)) &&
// dateModel.isBefore(lastDayOfMonth)) {
// index = i;
// break;
// }
// }
// WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
// calendarProvider.calendarConfiguration.monthController.jumpToPage(index);
// });
if ((dateModel.isAfter(firstDayOfMonth) ||
dateModel.isSameWith(firstDayOfMonth)) &&
dateModel.isBefore(lastDayOfMonth)) {
index = i;
break;
}
}
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
calendarProvider.calendarConfiguration.pageController.jumpToPage(index);
});
} }
@override @override
void dispose() { void dispose() {
LogUtil.log(TAG: this.runtimeType, message: "MonthViewPager dispose");
super.dispose(); super.dispose();
} }
@ -64,8 +72,12 @@ class _MonthViewPagerState extends State<MonthViewPager> {
// //
DateModel dateModel = configuration.monthList[position]; DateModel dateModel = configuration.monthList[position];
configuration.monthChange(dateModel.year, dateModel.month); configuration.monthChange(dateModel.year, dateModel.month);
// //
calendarProvider.lastClickDateModel = configuration.monthList[position]; DateModel temp = new DateModel();
temp.year = configuration.monthList[position].year;
temp.month = configuration.monthList[position].month;
temp.day = configuration.monthList[position].day + 14;
calendarProvider.lastClickDateModel = temp;
//使PageView //使PageView
// double itemHeight = MediaQuery.of(context).size.width / 7; // double itemHeight = MediaQuery.of(context).size.width / 7;
@ -81,21 +93,13 @@ class _MonthViewPagerState extends State<MonthViewPager> {
// }); // });
// } // }
}, },
controller: configuration.pageController, controller: configuration.monthController,
itemBuilder: (context, index) { itemBuilder: (context, index) {
DateModel dateModel = configuration.monthList[index]; final DateModel dateModel = configuration.monthList[index];
return new MonthView( return new MonthView(
configuration: configuration,
year: dateModel.year, year: dateModel.year,
month: dateModel.month, month: dateModel.month,
minSelectDate: DateModel.fromDateTime(DateTime(
configuration.minSelectYear,
configuration.minSelectMonth,
configuration.minSelectDay)),
maxSelectDate: DateModel.fromDateTime(DateTime(
configuration.maxSelectYear,
configuration.maxSelectMonth,
configuration.maxSelectDay)),
extraDataMap: configuration.extraDataMap,
); );
}, },
itemCount: configuration.monthList.length, itemCount: configuration.monthList.length,

@ -5,6 +5,7 @@ import 'package:flutter_custom_calendar/constants/constants.dart';
import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.dart'; import 'package:flutter_custom_calendar/model/date_model.dart';
import 'package:flutter_custom_calendar/utils/date_util.dart'; import 'package:flutter_custom_calendar/utils/date_util.dart';
import 'package:flutter_custom_calendar/widget/month_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
/** /**
@ -14,19 +15,13 @@ class WeekView extends StatefulWidget {
final int year; final int year;
final int month; final int month;
final DateModel firstDayOfWeek; final DateModel firstDayOfWeek;
final CalendarConfiguration configuration;
final DateModel minSelectDate;
final DateModel maxSelectDate;
final Map<DateModel, Object> extraDataMap; //
const WeekView( const WeekView(
{@required this.year, {@required this.year,
@required this.month, @required this.month,
this.firstDayOfWeek, this.firstDayOfWeek,
this.minSelectDate, this.configuration});
this.maxSelectDate,
this.extraDataMap});
@override @override
_WeekViewState createState() => _WeekViewState(); _WeekViewState createState() => _WeekViewState();
@ -35,87 +30,67 @@ class WeekView extends StatefulWidget {
class _WeekViewState extends State<WeekView> { class _WeekViewState extends State<WeekView> {
List<DateModel> items; List<DateModel> items;
DateModel minSelectDate;
DateModel maxSelectDate;
Map<DateModel, Object> extraDataMap; //
@override @override
void initState() { void initState() {
super.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( items = DateUtil.initCalendarForWeekView(
widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0, widget.year, widget.month, widget.firstDayOfWeek.getDateTime(), 0,
minSelectDate: widget.minSelectDate, minSelectDate: minSelectDate,
maxSelectDate: widget.maxSelectDate, maxSelectDate: maxSelectDate,
extraDataMap: widget.extraDataMap); extraDataMap: extraDataMap);
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<CalendarProvider>( CalendarProvider calendarProvider =
builder: (context, calendarProvider, child) { Provider.of<CalendarProvider>(context, listen: false);
CalendarConfiguration configuration =
calendarProvider.calendarConfiguration; CalendarConfiguration configuration =
print( calendarProvider.calendarConfiguration;
"WeekView Consumer:calendarProvider.selectDateModel:${calendarProvider.selectDateModel}"); print(
return new GridView.builder( "WeekView Consumer:calendarProvider.selectDateModel:${calendarProvider.selectDateModel}");
physics: NeverScrollableScrollPhysics(), return new GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount( physics: NeverScrollableScrollPhysics(),
crossAxisCount: 7, mainAxisSpacing: 10), gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
itemCount: 7, crossAxisCount: 7, mainAxisSpacing: 10),
itemBuilder: (context, index) { itemCount: 7,
DateModel dateModel = items[index]; itemBuilder: (context, index) {
// DateModel dateModel = items[index];
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) { //
if (calendarProvider.selectedDateList.contains(dateModel)) { if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
dateModel.isSelected = true; if (calendarProvider.selectedDateList.contains(dateModel)) {
} else { dateModel.isSelected = true;
dateModel.isSelected = false;
}
} else { } else {
if (calendarProvider.selectDateModel == dateModel) { dateModel.isSelected = false;
dateModel.isSelected = true;
} else {
dateModel.isSelected = false;
}
} }
} else {
if (calendarProvider.selectDateModel == dateModel) {
dateModel.isSelected = true;
} else {
dateModel.isSelected = false;
}
}
return GestureDetector( return ItemContainer(
onTap: () { dateModel: dateModel,
// // configuration: configuration,
print("GestureDetector onTap$dateModel"); // calendarProvider: calendarProvider,
print("!dateModel.isInRange:${!dateModel.isInRange}"); );
if (!dateModel.isInRange) { });
//
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
configuration.multiSelectOutOfRange();
}
return;
}
calendarProvider.lastClickDateModel = dateModel;
if (configuration.selectMode == Constants.MODE_MULTI_SELECT) {
//
if (calendarProvider.selectedDateList.length ==
configuration.maxMultiSelectCount) {
configuration.multiSelectOutOfSize();
return;
}
//
calendarProvider.selectDateModel = dateModel;
configuration.calendarSelect(dateModel);
// setState(() {
if (calendarProvider.selectedDateList.contains(dateModel)) {
calendarProvider.selectedDateList.remove(dateModel);
} else {
calendarProvider.selectedDateList.add(dateModel);
}
// });
} else {
calendarProvider.selectDateModel = dateModel;
configuration.calendarSelect(dateModel);
// setState(() {});
}
},
child: configuration.dayWidgetBuilder(dateModel),
);
});
});
} }
} }

@ -3,11 +3,12 @@ import 'package:flutter_custom_calendar/calendar_provider.dart';
import 'package:flutter_custom_calendar/configuration.dart'; import 'package:flutter_custom_calendar/configuration.dart';
import 'package:flutter_custom_calendar/controller.dart'; import 'package:flutter_custom_calendar/controller.dart';
import 'package:flutter_custom_calendar/model/date_model.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'; import 'package:flutter_custom_calendar/widget/week_view.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class WeekViewPager extends StatefulWidget { class WeekViewPager extends StatefulWidget {
WeekViewPager(); const WeekViewPager({Key key}) : super(key: key);
@override @override
_WeekViewPagerState createState() => _WeekViewPagerState(); _WeekViewPagerState createState() => _WeekViewPagerState();
@ -17,45 +18,27 @@ class _WeekViewPagerState extends State<WeekViewPager> {
int lastMonth; // int lastMonth; //
CalendarProvider calendarProvider; CalendarProvider calendarProvider;
// PageController newPageController;
@override @override
void initState() { void initState() {
print("WeekViewPager initState"); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager initState");
calendarProvider = Provider.of<CalendarProvider>(context, listen: false); calendarProvider = Provider.of<CalendarProvider>(context, listen: false);
lastMonth = calendarProvider.lastClickDateModel.month; lastMonth = calendarProvider.lastClickDateModel.month;
//index
DateModel dateModel = calendarProvider.lastClickDateModel;
List<DateModel> weekList = calendarProvider.calendarConfiguration.weekList;
int index = 0;
for (int i = 0; i < weekList.length; i++) {
DateModel firstDayOfWeek = weekList[i];
DateModel lastDayOfWeek = DateModel.fromDateTime(
firstDayOfWeek.getDateTime().add(Duration(days: 7)));
if ((dateModel.isSameWith(weekList[i]) ||
dateModel.isAfter(weekList[i])) &&
dateModel.isBefore(lastDayOfWeek)) {
index = i;
break;
}
}
// print("weekList:$weekList");
// print("当前周:index:$index");
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
calendarProvider.calendarConfiguration.weekController.jumpToPage(index);
});
} }
@override @override
void dispose() { void dispose() {
print("WeekViewPager dispose"); LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager dispose");
super.dispose(); super.dispose();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
LogUtil.log(TAG: this.runtimeType, message: "WeekViewPager build");
// CalendarProvider,listenfalse // CalendarProvider,listenfalse
CalendarProvider calendarProvider = CalendarProvider calendarProvider =
Provider.of<CalendarProvider>(context, listen: false); Provider.of<CalendarProvider>(context, listen: false);
@ -63,6 +46,7 @@ class _WeekViewPagerState extends State<WeekViewPager> {
calendarProvider.calendarConfiguration; calendarProvider.calendarConfiguration;
return Container( return Container(
height: configuration.itemSize ?? MediaQuery.of(context).size.width / 7,
child: PageView.builder( child: PageView.builder(
onPageChanged: (position) { onPageChanged: (position) {
// //
@ -71,28 +55,19 @@ class _WeekViewPagerState extends State<WeekViewPager> {
if (lastMonth != currentMonth) { if (lastMonth != currentMonth) {
configuration.monthChange( configuration.monthChange(
firstDayOfWeek.year, firstDayOfWeek.month); firstDayOfWeek.year, firstDayOfWeek.month);
lastMonth = currentMonth;
} }
calendarProvider.lastClickDateModel = // calendarProvider.lastClickDateModel = configuration.weekList[position]
configuration.weekList[position]; // ..day += 4;
// DateModel dateModel = configuration.weekList[position];
// configuration.monthChange(dateModel.year, dateModel.month);
}, },
controller: configuration.weekController, controller: calendarProvider.calendarConfiguration.weekController,
itemBuilder: (context, index) { itemBuilder: (context, index) {
DateModel dateModel = configuration.weekList[index]; DateModel dateModel = configuration.weekList[index];
return new WeekView( return new WeekView(
year: dateModel.year, year: dateModel.year,
month: dateModel.month, month: dateModel.month,
firstDayOfWeek: dateModel, firstDayOfWeek: dateModel,
minSelectDate: DateModel.fromDateTime(DateTime( configuration: calendarProvider.calendarConfiguration,
configuration.minSelectYear,
configuration.minSelectMonth,
configuration.minSelectDay)),
maxSelectDate: DateModel.fromDateTime(DateTime(
configuration.maxSelectYear,
configuration.maxSelectMonth,
configuration.maxSelectDay)),
extraDataMap: configuration.extraDataMap,
); );
}, },
itemCount: configuration.weekList.length, itemCount: configuration.weekList.length,

Loading…
Cancel
Save