如何在 flutter 上禁用特定日期列表
How to disable list of specific date on flutter
我有一个调用 showDatePicker 的代码,我的问题是如何禁用特定日期、一个、两个或更多 json 日期的列表?
我尝试禁用周六和周日的 selectableDayPredicate,但是如何禁用 json 来自 api 的日期列表?
onTap: () {
showDatePicker(
context: context,
initialDate:
DateTime.now().add(Duration(days: 2)),
firstDate:
DateTime.now().add(Duration(days: 1)),
lastDate:
DateTime.now().add(Duration(days: 730)),
selectableDayPredicate: (DateTime val) =>
val.weekday == 5 || val.weekday == 6
? false
: true,
);
}
这在很大程度上取决于您从 API 获得的数据。我帮不了你,但是谓词我可以。
假设您已经从您的服务器检索到一个包含一堆字符串的 json 列表,将它们解析为 DateTime 对象(可能使用 DateTime.parse 之类的东西),那么它就相对简单了。
基本上,您需要检查每个日期(使用 selectableDayPredicate)并且 return 如果它不在您的列表中则为真。
首先,您需要清理 DateTime 对象,因为它们可能包含小时、秒、毫秒等。您需要将它们转换为可以快速搜索的格式 - 所以可能不是 DateTime。 DateTimes 在技术上可以工作,因为它们确实具有 hashCode 实现,但您必须创建新的 DateTime 对象,无论如何只包含年、月和日(因为 +1 毫秒的日期时间在技术上与没有它的值不同)。如果你真的想那样做,你可以将下面的 sanitizeDateTime
函数更改为 return a DateTime
并将 getDateSet
更改为 return a Set<DateTime>
,但我建议将它们制作成字符串,因为它们在集合中运行良好且简单。
所以你需要一个像这样的函数:
String sanitizeDateTime(DateTime dateTime) => "${dateTime.year}-${dateTime.month}-${dateTime.day}";
无论你在哪里拿到你的json,你都会想用它来格式化它并将它插入到一个集合中。
Set<String> getDateSet(List<DateTime> dates) => dates.map(sanitizeDateTime).toSet();
重要的是你有一组字符串而不是一个列表,因为 selectableDayPredicate 会 运行 很多次,如果你每次都遍历整个不可选择的日期列表(这List 的 contains
所做的),它可能会变慢,因为它是 O(n*m)
,其中 n
是要检查的日期数,m
是不可选择的日期数 - 而如果你使用一个集合,contains
使用更有效的散列计算,然后查找结果 O(n)
。这可能被解释为过早的优化,但在这种情况下,我认为这是值得的。
一旦你有了一组不可选择的日期,你只需在谓词中检查它们。
即
class .... {
Set<String> unselectableDates; // assuming this is set somewhere
....
onTap: () {
showDatePicker(
...
selectableDayPredicate: (DateTime val) {
String sanitized = sanitizeDateTime(val);
return !unselectableDates.contains(sanitized);
}
}
}
我有一个调用 showDatePicker 的代码,我的问题是如何禁用特定日期、一个、两个或更多 json 日期的列表? 我尝试禁用周六和周日的 selectableDayPredicate,但是如何禁用 json 来自 api 的日期列表?
onTap: () {
showDatePicker(
context: context,
initialDate:
DateTime.now().add(Duration(days: 2)),
firstDate:
DateTime.now().add(Duration(days: 1)),
lastDate:
DateTime.now().add(Duration(days: 730)),
selectableDayPredicate: (DateTime val) =>
val.weekday == 5 || val.weekday == 6
? false
: true,
);
}
这在很大程度上取决于您从 API 获得的数据。我帮不了你,但是谓词我可以。
假设您已经从您的服务器检索到一个包含一堆字符串的 json 列表,将它们解析为 DateTime 对象(可能使用 DateTime.parse 之类的东西),那么它就相对简单了。
基本上,您需要检查每个日期(使用 selectableDayPredicate)并且 return 如果它不在您的列表中则为真。
首先,您需要清理 DateTime 对象,因为它们可能包含小时、秒、毫秒等。您需要将它们转换为可以快速搜索的格式 - 所以可能不是 DateTime。 DateTimes 在技术上可以工作,因为它们确实具有 hashCode 实现,但您必须创建新的 DateTime 对象,无论如何只包含年、月和日(因为 +1 毫秒的日期时间在技术上与没有它的值不同)。如果你真的想那样做,你可以将下面的 sanitizeDateTime
函数更改为 return a DateTime
并将 getDateSet
更改为 return a Set<DateTime>
,但我建议将它们制作成字符串,因为它们在集合中运行良好且简单。
所以你需要一个像这样的函数:
String sanitizeDateTime(DateTime dateTime) => "${dateTime.year}-${dateTime.month}-${dateTime.day}";
无论你在哪里拿到你的json,你都会想用它来格式化它并将它插入到一个集合中。
Set<String> getDateSet(List<DateTime> dates) => dates.map(sanitizeDateTime).toSet();
重要的是你有一组字符串而不是一个列表,因为 selectableDayPredicate 会 运行 很多次,如果你每次都遍历整个不可选择的日期列表(这List 的 contains
所做的),它可能会变慢,因为它是 O(n*m)
,其中 n
是要检查的日期数,m
是不可选择的日期数 - 而如果你使用一个集合,contains
使用更有效的散列计算,然后查找结果 O(n)
。这可能被解释为过早的优化,但在这种情况下,我认为这是值得的。
一旦你有了一组不可选择的日期,你只需在谓词中检查它们。
即
class .... {
Set<String> unselectableDates; // assuming this is set somewhere
....
onTap: () {
showDatePicker(
...
selectableDayPredicate: (DateTime val) {
String sanitized = sanitizeDateTime(val);
return !unselectableDates.contains(sanitized);
}
}
}