You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
flutter_custom_calendar/lib/controller.dart

601 lines
19 KiB

import 'dart:collection';
6 years ago
import 'package:flutter/material.dart';
5 years ago
import 'calendar_provider.dart';
import 'configuration.dart';
import 'constants/constants.dart';
import 'flutter_custom_calendar.dart';
import 'utils/LogUtil.dart';
import 'utils/date_util.dart';
import 'widget/default_combine_day_view.dart';
import 'widget/default_custom_day_view.dart';
import 'widget/default_week_bar.dart';
import 'model/date_model.dart';
6 years ago
/**
* controller
*/
class CalendarController {
static const Set<DateTime> EMPTY_SET = {};
static const Map<DateModel, Object> EMPTY_MAP = {};
static const Duration DEFAULT_DURATION = const Duration(milliseconds: 500);
6 years ago
CalendarConfiguration calendarConfiguration;
6 years ago
CalendarProvider calendarProvider = CalendarProvider();
6 years ago
/**
*
*/
List<DateModel> monthList = new List(); //月份list
List<DateModel> weekList = new List(); //星期list
PageController monthController; //月份的controller
PageController weekController; //星期的controller
6 years ago
CalendarController(
5 years ago
{CalendarSelectedMode selectMode = CalendarSelectedMode.singleSelect,
int showMode = CalendarConstants.MODE_SHOW_ONLY_MONTH,
6 years ago
int minYear = 1971,
int maxYear = 2055,
int minYearMonth = 1,
int maxYearMonth = 12,
int nowYear,
int nowMonth,
6 years ago
int minSelectYear = 1971,
int minSelectMonth = 1,
int minSelectDay = 1,
int maxSelectYear = 2055,
int maxSelectMonth = 12,
int maxSelectDay = 30,
Set<DateTime> selectedDateTimeList = EMPTY_SET, //多选模式下默认选中的item列表
DateModel selectDateModel, //单选模式下默认选中的item
6 years ago
int maxMultiSelectCount = 9999,
Map<DateModel, Object> extraDataMap = EMPTY_MAP,
int offset = 0 // 首日偏移量
5 years ago
}) {
assert(offset >= 0 && offset <= 6);
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,
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,
offset: offset);
calendarConfiguration.defaultSelectedDateList = new HashSet<DateModel>();
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));
6 years ago
LogUtil.log(
TAG: this.runtimeType,
message: "start:${DateModel.fromDateTime(DateTime(
minYear,
minYearMonth,
))},end:${DateModel.fromDateTime(DateTime(
maxYear,
maxYearMonth,
))}");
if (showMode != CalendarConstants.MODE_SHOW_ONLY_WEEK) {
//初始化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 (i == nowYear && j == nowMonth) {
initialPage = nowMonthIndex;
}
monthList.add(dateModel);
nowMonthIndex++;
}
}
this.monthController =
new PageController(initialPage: initialPage, keepPage: true);
LogUtil.log(
TAG: this.runtimeType,
message:
"初始化月份视图的信息:一共有${monthList.length}个月initialPage为$nowMonthIndex");
}
if (showMode != CalendarConstants.MODE_SHOW_ONLY_MONTH) {
//计算一共多少周
//计算方法:第一天是周几,最后一天是周几,中间的天数/7后加上2就是结果了
int initialWeekPage = 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);
}
calendarConfiguration.monthList = monthList;
calendarConfiguration.weekList = weekList;
calendarConfiguration.monthController = monthController;
calendarConfiguration.weekController = weekController;
6 years ago
}
//周视图切换
5 years ago
void addWeekChangeListener(OnWeekChange listener) {
this.calendarConfiguration.weekChangeListeners.add(listener);
}
6 years ago
//月份切换监听
void addMonthChangeListener(OnMonthChange listener) {
// this.calendarConfiguration.monthChange = listener;
this.calendarConfiguration.monthChangeListeners.add(listener);
6 years ago
}
//点击选择监听
void addOnCalendarSelectListener(OnCalendarSelect listener) {
this.calendarConfiguration.calendarSelect = listener;
6 years ago
}
5 years ago
//点击选择取消监听
void addOnCalendarUnSelectListener(OnCalendarUnSelect listener) {
this.calendarConfiguration.unCalendarSelect = listener;
}
6 years ago
//多选超出指定范围
void addOnMultiSelectOutOfRangeListener(OnMultiSelectOutOfRange listener) {
this.calendarConfiguration.multiSelectOutOfRange = listener;
6 years ago
}
//多选超出限制个数
void addOnMultiSelectOutOfSizeListener(OnMultiSelectOutOfSize listener) {
this.calendarConfiguration.multiSelectOutOfSize = listener;
6 years ago
}
//切换展开状态
void toggleExpandStatus() {
calendarProvider.expandStatus.value = !calendarProvider.expandStatus.value;
LogUtil.log(
TAG: this.runtimeType,
message: "toggleExpandStatus${calendarProvider.expandStatus.value}");
}
//监听展开变化
void addExpandChangeListener(ValueChanged<bool> expandChange) {
calendarProvider.expandStatus.addListener(() {
expandChange(calendarProvider.expandStatus.value);
});
}
//可以动态修改extraDataMap
void changeExtraData(Map<DateModel, Object> newMap) {
this.calendarConfiguration.extraDataMap = newMap;
this.calendarProvider.generation.value++;
}
//可以动态修改默认选中的item。
void changeDefaultSelectedDateList(Set<DateModel> defaultSelectedDateList) {
this.calendarConfiguration.defaultSelectedDateList =
defaultSelectedDateList;
this.calendarProvider.generation.value++;
}
//可以动态修改默认选中的item
void changeDefaultSelectedDateModel(DateModel dateModel) {
this.calendarProvider.selectDateModel = dateModel;
this.calendarProvider.generation.value++;
}
/**
*
*/
Future<bool> previousPage() async {
if (calendarProvider.expandStatus.value == true) {
//月视图
int currentIndex =
calendarProvider.calendarConfiguration.monthController.page.toInt();
if (currentIndex == 0) {
return false;
} else {
calendarProvider.calendarConfiguration.monthController
.previousPage(duration: DEFAULT_DURATION, curve: Curves.ease);
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;
temp.day = monthList[currentIndex].day + 14;
calendarProvider.lastClickDateModel = temp;
return true;
}
} else {
//周视图
int currentIndex =
calendarProvider.calendarConfiguration.weekController.page.toInt();
if (currentIndex == 0) {
return false;
} else {
calendarProvider.calendarConfiguration.weekController
.previousPage(duration: DEFAULT_DURATION, curve: Curves.ease);
return true;
}
}
}
/**
*
* true
* false:
*/
Future<bool> nextPage() async {
if (calendarProvider.expandStatus.value == true) {
//月视图
int currentIndex =
calendarProvider.calendarConfiguration.monthController.page.toInt();
if (monthList.length - 1 == currentIndex) {
return false;
} else {
calendarProvider.calendarConfiguration.monthController
.nextPage(duration: DEFAULT_DURATION, curve: Curves.ease);
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;
temp.day = monthList[currentIndex].day + 14;
calendarProvider.lastClickDateModel = temp;
return true;
}
} else {
//周视图
int currentIndex =
calendarProvider.calendarConfiguration.weekController.page.toInt();
if (weekList.length - 1 == currentIndex) {
return false;
} else {
calendarProvider.calendarConfiguration.weekController
.nextPage(duration: DEFAULT_DURATION, curve: Curves.ease);
return true;
}
}
}
6 years ago
//跳转到指定日期
void moveToCalendar(int year, int month, int day,
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) {
if (calendarProvider.expandStatus.value == true) {
DateModel dateModel = DateModel.fromDateTime(DateTime(year, month, 1));
//计算目标索引
int targetPage = monthList.indexOf(dateModel);
if (targetPage == -1) {
return;
}
if (calendarProvider.calendarConfiguration.monthController.hasClients ==
false) {
return;
}
if (needAnimation) {
calendarProvider.calendarConfiguration.monthController
.animateToPage(targetPage, duration: duration, curve: curve);
} else {
calendarProvider.calendarConfiguration.monthController
.jumpToPage(targetPage);
}
6 years ago
} else {
DateModel dateModel = DateModel.fromDateTime(DateTime(year, month, 1));
//计算目标索引
int targetPage = 0;
for (int i = 0; i < weekList.length - 1; i++) {
DateModel first = weekList[i];
DateModel next = weekList[i + 1];
if (!first.isAfter(dateModel) && next.isAfter(dateModel)) {
targetPage = i;
return;
}
}
if (calendarProvider.calendarConfiguration.weekController.hasClients ==
false) {
return;
}
if (needAnimation) {
calendarProvider.calendarConfiguration.weekController
.animateToPage(targetPage, duration: duration, curve: curve);
} else {
calendarProvider.calendarConfiguration.weekController
.jumpToPage(targetPage);
}
6 years ago
}
}
//切换到下一年
void moveToNextYear(
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) {
DateTime targetDateTime = monthList[calendarProvider
.calendarConfiguration.monthController.page
.toInt() +
12]
.getDateTime();
6 years ago
moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve);
}
//切换到上一年
void moveToPreviousYear(
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) {
DateTime targetDateTime = monthList[calendarProvider
.calendarConfiguration.monthController.page
.toInt() -
12]
.getDateTime();
6 years ago
moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve);
}
//切换到下一个月份,
void moveToNextMonth(
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) {
// 如果当前显示的是周视图的话需要计算出第一个月的index后调用weekController
if (calendarProvider.expandStatus.value == false) {
int currentMonth = weekList[calendarProvider
.calendarConfiguration.weekController.page
.toInt()]
.month;
for (int i = calendarProvider.calendarConfiguration.weekController.page
.toInt();
i < weekList.length;
i++) {
if (weekList[i].month != currentMonth) {
calendarProvider.calendarConfiguration.weekController.jumpToPage(i);
break;
}
}
return;
}
if ((calendarProvider.calendarConfiguration.monthController.page.toInt() +
1) >=
monthList.length) {
LogUtil.log(TAG: this.runtimeType, message: "moveToNextMonth当前是最后一个月份");
return;
}
DateTime targetDateTime = monthList[calendarProvider
.calendarConfiguration.monthController.page
.toInt() +
1]
.getDateTime();
6 years ago
moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve);
}
//切换到上一个月份
void moveToPreviousMonth(
{bool needAnimation = false,
Duration duration = const Duration(milliseconds: 500),
Curve curve = Curves.ease}) {
// 如果当前显示的是周视图的话需要计算出第一个月的index后调用weekController
if (calendarProvider.expandStatus.value == false) {
int currentMonth = weekList[weekController.page.toInt()].month;
for (int i = calendarProvider.calendarConfiguration.weekController.page
.toInt();
i >= 0;
i--) {
if (weekList[i].month != currentMonth &&
weekList[i].isAfter(DateModel.fromDateTime(DateTime(
calendarConfiguration.minYear,
calendarConfiguration.minYearMonth)))) {
calendarProvider.calendarConfiguration.weekController.jumpToPage(i);
break;
}
}
return;
}
if ((calendarProvider.calendarConfiguration.monthController.page.toInt()) ==
0) {
LogUtil.log(
TAG: this.runtimeType, message: "moveToPreviousMonth当前是第一个月份");
return;
}
DateTime targetDateTime = monthList[calendarProvider
.calendarConfiguration.monthController.page
.toInt() -
1]
.getDateTime();
6 years ago
moveToCalendar(
targetDateTime.year, targetDateTime.month, targetDateTime.day,
needAnimation: needAnimation, duration: duration, curve: curve);
}
// 获取当前的月份
DateModel getCurrentMonth() {
return monthList[monthController.page.toInt()];
6 years ago
}
//获取被选中的日期,多选
Set<DateModel> getMultiSelectCalendar() {
return calendarProvider.selectedDateList;
6 years ago
}
//获取被选中的日期,单选
DateModel getSingleSelectCalendar() {
return calendarProvider.selectDateModel;
6 years ago
}
//清除数据
void clearData() {
monthList.clear();
weekList.clear();
calendarProvider.clearData();
5 years ago
calendarConfiguration.weekChangeListeners = null;
calendarConfiguration.monthChangeListeners = null;
}
6 years ago
}
/**
* weekBar
*/
Widget defaultWeekBarWidget() {
return const DefaultWeekBar();
6 years ago
}
/**
* 使canvasitem
*/
Widget defaultCustomDayWidget(DateModel dateModel) {
return DefaultCustomDayWidget(
dateModel,
);
}
/**
* 使widgetitem
*/
Widget defaultCombineDayWidget(DateModel dateModel) {
return new DefaultCombineDayWidget(
dateModel,
);
}
/**
*
*/
bool defaultInRange(DateModel dateModel) {
return true;
}
/**
*
*/
typedef void OnWeekChange(int year, int month);
6 years ago
/**
*
*/
typedef void OnMonthChange(int year, int month);
/**
*
*/
typedef void OnCalendarSelect(DateModel dateModel);
5 years ago
/**
*
*/
typedef void OnCalendarUnSelect(DateModel dateModel);
6 years ago
/**
*
*/
typedef void OnMultiSelectOutOfRange();
/**
*
*/
typedef void OnMultiSelectOutOfSize();
/**
* item
*/
typedef Widget DayWidgetBuilder(DateModel dateModel);
/**
*
*/
typedef bool CanClick(DateModel dateModel);
/**
* Item
*/
typedef void DrawDayWidget(DateModel dateModel, Canvas canvas, Size size);
/**
* weekBar
*/
typedef Widget WeekBarItemWidgetBuilder();