如何在 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);
        }
    }
}