背景描述
最近接到了一个日历需求,类似于钉钉的日历,需要能在周日历和月日历间来回切换。其中要实现下面2点功能:
1.日历左滑/右滑切换视图的时候,需要重新定位选中日期
2.在月日历上选中日期的时候,要自动切回周日历
类似以下钉钉截图:
周日历:
月日历:
问题描述
日期控件用了这个库:syncfusion_flutter_datepicker 23.2.7,刚开始代码是这样写的(这里只展示关键代码):
int numberOfWeeksInView = 1; // 视图周数:周日历是1周,月日历是6周。这里默认1,即默认显示周日历。
// 创建日历
Stack(
children: [
calendarPicker,
switchBtn
]
);
Widget calendarPicker(){
return SfDateRangePicker(
numberOfWeeksInView: numberOfWeeksInView,
// 日期选择事件
onSelectionChanged: (DateRangePickerSelectionChangedArgs args) {
print('onSelectionChanged-${widget.controller.selectedDate}');
changeToWeekView(); // 在月日历上选中日期的时候,要自动切回周日历
WidgetsBinding.instance.addPostFrameCallback((_) {
widget.controller.displayDate = widget.controller.selectedDate;
});
request();
},
// 月份切换事件
onViewChanged: (DateRangePickerViewChangedArgs args) {
WidgetsBinding.instance.addPostFrameCallback((_) {
print(
'onViewChanged-${widget.controller.selectedDate}-${widget.controller.displayDate}');
// 日历左滑/右滑切换视图的时候,需要重新定位选中日期
widget.controller.selectedDate = widget.controller.displayDate;
});
},
);
}
// 切换周/月的按钮
Widget switchBtn(){
return GestureDetector(
onTap: () {
setState(() {
if (myNumberOfWeeksInView.value == 1) {
changeToMonthView();
} else {
changeToWeekView();
}
});
},
child: Text('切换')
);
}
// 请求后台数据
request() {
print('request');
}
// 变为周日历
changeToWeekView() {
setState(() {
numberOfWeeksInView = 1;
}
}
// 变为月日历
changeToMonthView() {
setState(() {
numberOfWeeksInView = 6;
}
}
这样写就带来了个很严重的问题,从周日历切到月日历,在月日历上左右滑动的时候,因为触发了onViewChanged事件,导致selectedDate重新赋值,接着就触发了onSelectionChanged事件,导致又切回了周日历。
尝试用一个变量进行加锁,加了一堆代码后,毫无疑问,把自己搞晕了 😵💫
解决方案
看了下官方库,发现有提供addPropertyChangedListener和removePropertyChangedListener方法,那就即刻用起来,哈哈😁
代码示例如下:
// 日期变量声明
DateRangePickerController dateRangePickerController =
DateRangePickerController();
// 日期事件监听方法
pickerValueChangedListener(String value) {
if (value == 'selectedDate') {
print('onSelectionChanged-${widget.controller.selectedDate}');
// 在月日历上选中日期的时候,要自动切回周日历
changeToWeekView();
WidgetsBinding.instance.addPostFrameCallback((_) {
widget.controller.displayDate = widget.controller.selectedDate;
});
request();
} else if (value == 'displayDate') {
// 移除监听事件,防止日历左右滑动会触发onSelectionChanged事件
removePickerListener();
WidgetsBinding.instance.addPostFrameCallback((_) {
print(
'onViewChanged-${widget.controller.selectedDate}-${widget.controller.displayDate}');
// 日历左滑/右滑切换视图的时候,需要重新定位选中日期
widget.controller.selectedDate = widget.controller.displayDate;
// 左右滑动结束后,重新绑定监听事件
addPickerListener();
});
}
}
// 添加日期事件监听方法
addPickerListener() {
dateRangePickerController
.addPropertyChangedListener(pickerValueChangedListener);
}
// 移除日期事件监听方法
removePickerListener() {
dateRangePickerController
.removePropertyChangedListener(pickerValueChangedListener);
}
引用
- syncfusion_flutter_datepicker的库地址:pub.dev/packages/sy…