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

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

@ -19,7 +19,7 @@ Flutter上的一个日历控件可以定制成自己想要的样子。
* 支持月份视图和星期视图的展示与切换联动 * 支持月份视图和星期视图的展示与切换联动
## 近期修改 ## 近期修改
### [1.0.0] - 2019/9/22 ### [1.0.0] - 2019/10/10
* 重构日历的代码,进行性能优化 * 重构日历的代码,进行性能优化
* 创建configuration类将配置的信息放到这里 * 创建configuration类将配置的信息放到这里
* 引入provider状态管理,避免深层嵌套传递信息 * 引入provider状态管理,避免深层嵌套传递信息
@ -123,6 +123,9 @@ extraDataMap | 自定义额外的数据| 默认为空MapMap<DateTime, Object>
:-: | :-: | :-: :-: | :-: | :-:
weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式 weekBarItemWidgetBuilder | 创建顶部的weekbar | 默认样式
dayWidgetBuilder | 创建日历item | 默认样式 dayWidgetBuilder | 创建日历item | 默认样式
verticalSpacing|日历item之间的竖直方向间距|默认10
boxDecoration |整体的背景设置|
itemSize| 每个item的边长|默认是屏幕宽度/7|
### 事件监听的配置 ### 事件监听的配置

@ -1,3 +1,4 @@
import 'package:example/only_week_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'custom_sign_page.dart'; import 'custom_sign_page.dart';
@ -6,7 +7,7 @@ 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(){ void main() {
// debugProfileBuildsEnabled=true; // debugProfileBuildsEnabled=true;
// debugProfilePaintsEnabled=true; // debugProfilePaintsEnabled=true;
runApp(MyApp()); runApp(MyApp());
@ -33,7 +34,10 @@ class MyApp extends StatelessWidget {
), ),
"/custom_sign": (context) => CustomSignPage( "/custom_sign": (context) => CustomSignPage(
title: "自定义额外数据,实现标记功能", title: "自定义额外数据,实现标记功能",
) ),
"/only_week_view": (context) => OnlyWeekPage(
title: "仅显示周视图",
),
}, },
title: 'Flutter Demo', title: 'Flutter Demo',
theme: ThemeData( theme: ThemeData(
@ -80,6 +84,12 @@ class HomePage extends StatelessWidget {
}, },
child: new Text("自定义额外数据,实现标记功能"), child: new Text("自定义额外数据,实现标记功能"),
), ),
new RaisedButton(
onPressed: () {
Navigator.pushNamed(context, "/only_week_view");
},
child: new Text("仅显示周视图"),
),
], ],
), ),
), ),

@ -43,13 +43,13 @@ class _MultiSelectStylePageState extends State<MultiSelectStylePage> {
controller.addOnCalendarSelectListener((dateModel) { controller.addOnCalendarSelectListener((dateModel) {
// //
selectText.value = selectText.value =
"选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"; "选模式\n选中的时间:\n${controller.getMultiSelectCalendar().join("\n")}";
}); });
text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}"); text = new ValueNotifier("${DateTime.now().year}${DateTime.now().month}");
selectText = new ValueNotifier( selectText = new ValueNotifier(
"选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}"); "选模式\n选中的时间:\n${controller.getSingleSelectCalendar()}");
} }
@override @override

@ -0,0 +1,101 @@
import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/flutter_custom_calendar.dart';
/**
* +
*/
class OnlyWeekPage extends StatefulWidget {
OnlyWeekPage({Key key, this.title}) : super(key: key);
final String title;
@override
_OnlyWeekPageState createState() => _OnlyWeekPageState();
}
class _OnlyWeekPageState extends State<OnlyWeekPage> {
ValueNotifier<String> text;
ValueNotifier<String> selectText;
CalendarController controller;
@override
void initState() {
DateTime now = DateTime.now();
controller = new CalendarController(
minYear: now.year,
minYearMonth: now.month - 2,
maxYear: now.year,
maxYearMonth: now.month + 1,
showMode: Constants.MODE_SHOW_ONLY_WEEK);
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) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: new Container(
child: new Column(
children: <Widget>[
new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new IconButton(
icon: Icon(Icons.navigate_before),
onPressed: () {
// controller.moveToPreviousMonth();
controller.previousPage();
}),
ValueListenableBuilder(
valueListenable: text,
builder: (context, value, child) {
return new Text(text.value);
}),
new IconButton(
icon: Icon(Icons.navigate_next),
onPressed: () {
// controller.moveToNextMonth();
controller.nextPage();
}),
],
),
CalendarViewWidget(
calendarController: controller,
),
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.
);
}
}

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_custom_calendar/cache_data.dart'; import 'package:flutter_custom_calendar/cache_data.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/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/utils/date_util.dart';
@ -78,7 +79,7 @@ class CalendarProvider extends ChangeNotifier {
return index + 1; return index + 1;
} }
ValueNotifier<bool> expandStatus = ValueNotifier(true); // ValueNotifier<bool> expandStatus; //
// //
CalendarConfiguration calendarConfiguration; CalendarConfiguration calendarConfiguration;
@ -98,12 +99,17 @@ class CalendarProvider extends ChangeNotifier {
? selectDateModel ? selectDateModel
: DateModel.fromDateTime(DateTime.now()) : DateModel.fromDateTime(DateTime.now())
..day = 15; ..day = 15;
if (calendarConfiguration.showMode == Constants.MODE_SHOW_ONLY_WEEK) {
expandStatus = ValueNotifier(false);
} else {
expandStatus = ValueNotifier(true);
}
} }
//退 //退
void clearData() { void clearData() {
LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider clearData"); LogUtil.log(TAG: this.runtimeType, message: "CalendarProvider clearData");
CacheData.instance.clearData(); CacheData.getInstance().clearData();
selectedDateList.clear(); selectedDateList.clear();
selectDateModel = null; selectDateModel = null;
calendarConfiguration = null; calendarConfiguration = null;

@ -83,36 +83,6 @@ class CalendarController {
}).toSet()); }).toSet());
} }
//pageController,initialPage
int initialPage = 0;
int nowMonthIndex = 0;
monthList.clear();
for (int i = minYear; i <= maxYear; i++) {
for (int j = 1; j <= 12; j++) {
if (i == minYear && j < minYearMonth) {
continue;
}
if (i == maxYear && j > maxYearMonth) {
continue;
}
DateModel dateModel = new DateModel();
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;
}
monthList.add(dateModel);
nowMonthIndex++;
}
}
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(
@ -122,35 +92,86 @@ class CalendarController {
maxYear, maxYear,
maxYearMonth, maxYearMonth,
))}"); ))}");
LogUtil.log(
TAG: this.runtimeType,
message:
"初始化月份视图的信息:一共有${monthList.length}个月initialPage为${nowMonthIndex}");
// if (showMode == Constants.MODE_SHOW_ONLY_MONTH ||
///72 showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) {
int initialWeekPage = 0; //pageController,initialPage
int nowWeekIndex = 0; int initialPage = 0;
weekList.clear(); int nowMonthIndex = 0;
monthList.clear();
for (int i = minYear; i <= maxYear; i++) {
for (int j = 1; j <= 12; j++) {
if (i == minYear && j < minYearMonth) {
continue;
}
if (i == maxYear && j > maxYearMonth) {
continue;
}
DateModel dateModel = new DateModel();
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;
}
monthList.add(dateModel);
nowMonthIndex++;
}
}
this.monthController =
new PageController(initialPage: initialPage, keepPage: true);
DateTime firstDayOfMonth = DateTime(minYear, minYearMonth, 1); LogUtil.log(
// TAG: this.runtimeType,
DateTime firstWeekDate = message:
firstDayOfMonth.add(Duration(days: -(firstDayOfMonth.weekday - 1))); "初始化月份视图的信息:一共有${monthList.length}个月initialPage为${nowMonthIndex}");
}
DateTime lastDay = DateTime(maxYear, maxYearMonth,
DateUtil.getMonthDaysCount(maxYear, maxYearMonth)); if (showMode == Constants.MODE_SHOW_ONLY_WEEK ||
for (DateTime dateTime = firstWeekDate; showMode == Constants.MODE_SHOW_WEEK_AND_MONTH) {
!dateTime.isAfter(lastDay); //
dateTime = dateTime.add(Duration(days: 7))) { ///72
DateModel dateModel = DateModel.fromDateTime(dateTime); int initialWeekPage = 0;
weekList.add(dateModel); int nowWeekIndex = 0;
weekList.clear();
//
if (nowYear == -1 || nowMonth == -1) {
nowYear = DateTime.now().year;
nowMonth = DateTime.now().month;
}
DateTime nowTime = new DateTime(nowYear, nowMonth, 15);
DateTime firstDayOfMonth = DateTime(minYear, minYearMonth, 1);
//
DateTime firstWeekDate =
firstDayOfMonth.add(Duration(days: -(firstDayOfMonth.weekday - 1)));
DateTime lastDay = DateTime(maxYear, maxYearMonth,
DateUtil.getMonthDaysCount(maxYear, maxYearMonth));
int temp = -1;
for (DateTime dateTime = firstWeekDate;
!dateTime.isAfter(lastDay);
dateTime = dateTime.add(Duration(days: 7))) {
DateModel dateModel = DateModel.fromDateTime(dateTime);
weekList.add(dateModel);
print("nowTime.isBefore(dateTime)");
print("$nowTime,,,,$dateTime");
if (nowTime.isAfter(dateTime)) {
temp++;
}
}
initialWeekPage = temp;
LogUtil.log(
TAG: this.runtimeType,
message:
"初始化星期视图的信息:一共有${weekList.length}个星期initialPage为${initialWeekPage}");
this.weekController = new PageController(initialPage: initialWeekPage);
} }
this.weekController = new PageController();
LogUtil.log(
TAG: this.runtimeType,
message:
"初始化星期视图的信息:一共有${weekList.length}个星期initialPage为${initialWeekPage}");
calendarConfiguration.monthList = monthList; calendarConfiguration.monthList = monthList;
calendarConfiguration.weekList = weekList; calendarConfiguration.weekList = weekList;
@ -442,12 +463,11 @@ class CalendarController {
} }
// //
void clearData(){ void clearData() {
monthList.clear(); monthList.clear();
weekList.clear(); weekList.clear();
calendarProvider.clearData(); calendarProvider.clearData();
} }
} }
/** /**

@ -54,13 +54,15 @@ class _CalendarViewWidgetState extends State<CalendarViewWidget> {
// //
decoration: widget.boxDecoration, decoration: widget.boxDecoration,
//使constsetStatewidget //使constsetStatewidget
child: const CalendarContainer()), child: CalendarContainer(widget.calendarController)),
); );
} }
} }
class CalendarContainer extends StatefulWidget { class CalendarContainer extends StatefulWidget {
const CalendarContainer(); final CalendarController calendarController;
const CalendarContainer(this.calendarController);
@override @override
CalendarContainerState createState() => CalendarContainerState(); CalendarContainerState createState() => CalendarContainerState();
@ -121,6 +123,28 @@ class CalendarContainerState extends State<CalendarContainer>
}); });
}); });
} }
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;
});
}
}
});
} }
@override @override
@ -134,40 +158,10 @@ class CalendarContainerState extends State<CalendarContainer>
//,,: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 = calendarProvider.calendarConfiguration.itemSize ?? itemHeight = calendarProvider.calendarConfiguration.itemSize ??
MediaQuery.of(context).size.width / 7; MediaQuery.of(context).size.width / 7;
totalHeight = itemHeight * 6 + 10 * (6 - 1); if (totalHeight == null) {
// return Container( totalHeight = itemHeight * 6 +
// child: new Column( calendarProvider.calendarConfiguration.verticalSpacing * (6 - 1);
// 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, width: itemHeight * 7,
child: new Column( child: new Column(
@ -182,7 +176,6 @@ class CalendarContainerState extends State<CalendarContainer>
duration: Duration(milliseconds: 500), duration: Duration(milliseconds: 500),
height: expand ? totalHeight : itemHeight, height: expand ? totalHeight : itemHeight,
child: IndexedStack( child: IndexedStack(
// overflow: Overflow.visible,
index: index, index: index,
children: widgets, children: widgets,
)), )),

@ -194,12 +194,12 @@ class ItemContainerState extends State<ItemContainer> {
return; return;
} }
configuration.calendarSelect(dateModel);
if (calendarProvider.selectedDateList.contains(dateModel)) { if (calendarProvider.selectedDateList.contains(dateModel)) {
calendarProvider.selectedDateList.remove(dateModel); calendarProvider.selectedDateList.remove(dateModel);
} else { } else {
calendarProvider.selectedDateList.add(dateModel); calendarProvider.selectedDateList.add(dateModel);
} }
configuration.calendarSelect(dateModel);
// //
calendarProvider.selectDateModel = dateModel; calendarProvider.selectDateModel = dateModel;

Loading…
Cancel
Save