Flutter中showDateRangePicker是否支持使用selectableDayPredicate的相关包?
实现方案
你需要的预约冲突拦截逻辑完全可以通过自定义selectableDayPredicate实现,原生showDateRangePicker的可选日期判断逻辑调整后可以完美适配民宿类预约的已预订日期屏蔽需求。
第一步:维护已预订的日期区间数据集
你需要先把后台返回的所有已被预约的时间段存成一个集合,示例如下:
// 示例已预订区间,实际场景从业务接口获取 List<DateTimeRange> bookedRanges = [ DateTimeRange(start: DateTime(2024,5,1), end: DateTime(2024,5,4)), DateTimeRange(start: DateTime(2024,5,10), end: DateTime(2024,5,15)), ];
第二步:实现日期是否被预订的判断方法
编写你提到的_isDateBooked方法,判断单个日期是否落在任意已预订区间内:
bool _isDateBooked(DateTime date) { // 清零时分秒,避免时间戳差异影响日期判断 DateTime normalizedDate = DateTime(date.year, date.month, date.day); for (var range in bookedRanges) { DateTime normalizedStart = DateTime(range.start.year, range.start.month, range.start.day); DateTime normalizedEnd = DateTime(range.end.year, range.end.month, range.end.day); // 日期落在[开始日, 结束日)区间内即属于已预订,不可选 if (normalizedDate.isAtSameMomentAs(normalizedStart) || (normalizedDate.isAfter(normalizedStart) && normalizedDate.isBefore(normalizedEnd))) { return true; } } return false; }
第三步:适配showDateRangePicker参数
注意原生showDateRangePicker的selectableDayPredicate回调默认仅接收单个当前判断的日期参数,基础实现代码如下:
showDateRangePicker( context: context, firstDate: DateTime.now(), lastDate: DateTime.now().add(const Duration(days: 365)), selectableDayPredicate: (DateTime date) { // 已预订的日期直接标记为不可选 return !_isDateBooked(date); }, );
进阶优化:禁止跨已预订区间选范围
如果你需要实现提问代码里传入已选中日期的判断逻辑,比如用户选了起始日之后,自动屏蔽和起始日之间存在已预订时段的结束日,可以扩展判断逻辑:
DateTime? selectedStartDate; // 存储用户已选中的起始日期 bool _isDateSelectable(DateTime date) { // 已预订日期直接不可选 if (_isDateBooked(date)) return false; // 已选起始日的情况下,校验起始日到当前日之间是否有已预订时段 if (selectedStartDate != null) { DateTime current = selectedStartDate!; while (current.isBefore(date)) { if (_isDateBooked(current)) { return false; } current = current.add(const Duration(days: 1)); } } return true; }
将上述方法传入selectableDayPredicate即可完全避免用户选中包含已预订时段的日期范围,不会出现预约冲突。
内容的提问来源于stack exchange,提问作者Keaton Mustard
相关产品推荐
相关产品推荐

