Skip to content

Conversation

@koukibadr
Copy link
Contributor

@koukibadr koukibadr commented Jun 28, 2025

Description

This PR enhances the CupertinoDatePicker by introducing a weekType parameter, giving developers more control over which days users can select.

Solution

To address this, I've added a new weekType parameter to the CupertinoDatePicker widget. This parameter offers a declarative way to control the set of selectable days displayed in the picker, with options defined in a new WeekType enum:

WeekType.workDays (Monday-Friday)

WeekType.weekends (Saturday-Sunday)

WeekType.fullWeek (all days, current default behavior)

WeekType.custom (allows developers to provide a List representing the DateTime.weekday values that should be visible and selectable).

Example

// Example: Display only work days (Monday-Friday)
CupertinoDatePicker(
  mode: CupertinoDatePickerMode.date,
  initialDateTime: DateTime.now(),
  minimumDate: DateTime(2023, 1, 1),
  maximumDate: DateTime(2024, 12, 31),
  weekType: WeekType.workDays,
  onDateTimeChanged: (DateTime newDateTime) {
    // Handle date change
  },
);

Screenshots

workdays_display.mov
weekend_display.mov
custom_weekdays.mov

Here's the linked issue to this PR #171332

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: cupertino flutter/packages/flutter/cupertino repository labels Jun 28, 2025
@alex-medinsh
Copy link
Contributor

Hi @koukibadr! I think the API can be simplified by removing the weekType parameter and enum altogether and allowing the developer to just specify customWeekDays? It will then default to all 7 days and we can then have static presets, something like:

  static const List<int> weekends = [
    DateTime.saturday, 
    DateTime.sunday
  ];

  static const List<int> workDays = [
    DateTime.monday,
    DateTime.tuesday,
    DateTime.wednesday,
    DateTime.thursday,
    DateTime.friday,
  ];

It seems to me that it will help simplify the implementation as well. What do you think?

@koukibadr
Copy link
Contributor Author

Hi @koukibadr! I think the API can be simplified by removing the weekType parameter and enum altogether and allowing the developer to just specify customWeekDays? It will then default to all 7 days and we can then have static presets, something like:

  static const List<int> weekends = [
    DateTime.saturday, 
    DateTime.sunday
  ];

  static const List<int> workDays = [
    DateTime.monday,
    DateTime.tuesday,
    DateTime.wednesday,
    DateTime.thursday,
    DateTime.friday,
  ];

It seems to me that it will help simplify the implementation as well. What do you think?

@alex-medinsh yes it would be more cleaner I agree, but how developers will use presets ? it should be part of the CupertinoDatePIcker class right ?

@victorsanni
Copy link
Contributor

Hi @koukibadr! I think the API can be simplified by removing the weekType parameter and enum altogether and allowing the developer to just specify customWeekDays? It will then default to all 7 days and we can then have static presets, something like:

Talking with @MitchellGoodwin offline we think an even more general API can solve this problem and provide more control to developers. For example, a bool callback with a DateTime date arg that returns true if the date should be enabled or not. @alex-medinsh @koukibadr what do you think?

@alex-medinsh
Copy link
Contributor

alex-medinsh commented Jun 30, 2025

it should be part of the CupertinoDatePIcker class right ?

@koukibadr Initially I was thinking yes, but I am not sure how clean that is.

For example, a bool callback with a DateTime date arg that returns true if the date should be enabled or not.

@victorsanni Does the callback get the currently selected value as the argument? I think this can a bit strange in terms of the UX, since user can select any date and only then will it evaluate if it is selectable. Or did I misunderstand what you were suggesting?

What I think this PR is trying to accomplish is something akin to minimumDate and maximumDate, but with weekdays, where the user doesn't even see the disabled options.

Nevermind. The callback seems like a nice solution. :)

@MitchellGoodwin
Copy link
Contributor

MitchellGoodwin commented Jun 30, 2025

The Material date picker has a similar way of validating dates through selectableDayPredicate. A callback is a bit more flexible compared to a list when the list has to be made dynamic anyway through things like valid dates depend on outside logic or localization.

how developers will use presets ? it should be part of the CupertinoDatePIcker class right ?
Theoretically an enum of default callbacks could be provided, but I worry that it would be difficult to iterate on this enum. There's also localizations concerns. For instance "workDays" isn't valid for a lot of people, if the targets of the app work weekends, or it's in a culture that has a different work week, it loses relevance quickly.

@koukibadr
Copy link
Contributor Author

The Material date picker has a similar way of validating dates through selectableDayPredicate. A callback is a bit more flexible compared to a list when the list has to be made dynamic anyway through things like valid dates depend on outside logic or localization.

how developers will use presets ? it should be part of the CupertinoDatePIcker class right ?
Theoretically an enum of default callbacks could be provided, but I worry that it would be difficult to iterate on this enum. There's also localizations concerns. For instance "workDays" isn't valid for a lot of people, if the targets of the app work weekends, or it's in a culture that has a different work week, it loses relevance quickly.

@victorsanni @alex-medinsh @MitchellGoodwin Okay it make sense especially following the same logic as material design date picker, I'll update the implementation then
thanks for these clarifications

@dkwingsmt dkwingsmt requested a review from MitchellGoodwin July 2, 2025 18:11
const double _kTimerPickerColumnIntrinsicWidth = 106;

/// Signature for predicating dates for enabled date selections.
typedef SelectableDayPredicate = bool Function(DateTime date);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This typedef is already defined in material/date.dart. Can we move some logic in that file to widgets/ and share it here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that date.dart is related to specific Material DatePickers but yes we can refactor to have only one SelectableDayPredicate makes more sense

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@koukibadr Do you plan to make this refactor? Just want to make sure we're on the same page. (from triage)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @dkwingsmt yes I'm back working on this just need to verify other Material DateTime features to not break anything with this refactor

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome. Take your time!

@github-actions github-actions bot added the f: material design flutter/packages/flutter/material repository. label Jul 25, 2025
Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @koukibadr. Can you resolve the merge conflicts, rebase, and change the title of the PR to match the latest changes?

@koukibadr
Copy link
Contributor Author

@victorsanni
Okay I'll update my branch then

@koukibadr koukibadr closed this Aug 9, 2025
@fluttergithubbot
Copy link
Contributor

An existing Git SHA, 1590543f6794addbb7dff8c6d655a7546eb955aa, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@koukibadr koukibadr reopened this Aug 9, 2025
@fluttergithubbot
Copy link
Contributor

An existing Git SHA, 301e896dbd6dd4ddeb68f7da99cde5ccb830906f, was detected, and no actions were taken.

To re-trigger presubmits after closing or re-opeing a PR, or pushing a HEAD commit (i.e. with --force) that already was pushed before, push a blank commit (git commit --allow-empty -m "Trigger Build") or rebase to continue.

@koukibadr
Copy link
Contributor Author

@victorsanni I've resolved the conflict and rebased latest master branch

@koukibadr koukibadr requested a review from victorsanni August 9, 2025 08:46
@victorsanni
Copy link
Contributor

Hi @koukibadr, can you run dart format packages/flutter/lib/src/cupertino/date_picker.dart to fix the failing Linux analyze test? The other failing test is a bot timeout which should be corrected once you push the formatting changes.

@koukibadr koukibadr requested a review from victorsanni August 17, 2025 14:48
@koukibadr koukibadr requested a review from victorsanni August 18, 2025 21:25
),
assert(
selectableDayPredicate == null ||
selectableDayPredicate(initialDateTime ?? DateTime.now()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure DateTime.now() should be used here. What about

selectableDayPredicate == null || initialDate == null || selectableDayPredicate!(this.initialDate!)

like in DatePicker?

Comment on lines 885 to 890
final bool isValidDate;
if (widget.selectableDayPredicate == null) {
isValidDate = true;
} else {
isValidDate = widget.selectableDayPredicate!.call(rangeStart);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace with a method:

  bool _isSelectable(DateTime date) {
    return widget.selectableDayPredicate?.call(date) ?? true;
  }

and call it with rangeStart:

return itemPositioningBuilder(context, Text(dateText, style: _themeTextStyle(context)));
return itemPositioningBuilder(
context,
Text(dateText, style: _themeTextStyle(context, isValid: isValidDate)),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Text(dateText, style: _themeTextStyle(context, isValid: isValidDate)),
Text(dateText, style: _themeTextStyle(context, isValid: _isSelectable(rangeStart)),

final DateTime selectedDate = selectedDateTime;
final bool minCheck = widget.minimumDate?.isAfter(selectedDate) ?? false;

if (widget.selectableDayPredicate?.call(selectedDate) == false) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_isSelectable can be used here as well. If needed, the function can be defined outside of any classes and pass in widget.selectableDayPredicate.

@koukibadr koukibadr requested a review from victorsanni August 23, 2025 08:44
Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM once comments are addressed.

@MitchellGoodwin
Copy link
Contributor

@koukibadr it looks like analyzer checks are failing for null check operators. Can you resolve them? The failures are in the Linux analyze check.

@koukibadr
Copy link
Contributor Author

@koukibadr it looks like analyzer checks are failing for null check operators. Can you resolve them? The failures are in the Linux analyze check.

I'll check them

@dkwingsmt dkwingsmt changed the title feat(cupertino): Add weekType parameter to CupertinoDatePicker for selectable day control #171332 feat(cupertino): Add selectableDayPredicate parameter to CupertinoDatePicker for selectable day control #171332 Sep 5, 2025
@koukibadr
Copy link
Contributor Author

@MitchellGoodwin I've updated the PR can you check again ?

Copy link
Contributor

@dkwingsmt dkwingsmt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

Copy link
Contributor

@MitchellGoodwin MitchellGoodwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM as well!

@dkwingsmt dkwingsmt added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 24, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Sep 24, 2025
Merged via the queue into flutter:master with commit d5b7f24 Sep 24, 2025
78 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 24, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 25, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Sep 25, 2025
auto-submit bot pushed a commit to flutter/packages that referenced this pull request Sep 25, 2025
Roll Flutter from 4a04204 to b1a28bc (44 revisions)

flutter/flutter@4a04204...b1a28bc

2025-09-25 48625061+muradhossin@users.noreply.github.com web_ui: avoid crash for showPerformanceOverlay; log 'not supported' once (flutter/flutter#173518)
2025-09-25 paulberry@google.com Ignore upcoming `experimental_member_use` warnings. (flutter/flutter#175969)
2025-09-25 engine-flutter-autoroll@skia.org Roll Skia from 753ce2221ce7 to 55436d87e414 (16 revisions) (flutter/flutter#176004)
2025-09-25 tirth@nevercode.io Add google_fonts to team-framework triage guidelines (flutter/flutter#175675)
2025-09-25 bruno.leroux@gmail.com Add tests for InputDecoration borders (M3 and theme normalization) (flutter/flutter#175838)
2025-09-24 737941+loic-sharma@users.noreply.github.com Update Flutter's templates to use dot shorthands (flutter/flutter#175891)
2025-09-24 matt.boetger@gmail.com In Gradle Flutter task, correctly replace '\ ' with ' '. (flutter/flutter#175815)
2025-09-24 47866232+chunhtai@users.noreply.github.com Cleans up navigator pop and remove logic (flutter/flutter#175612)
2025-09-24 rmolivares@renzo-olivares.dev Fix docs in `EditableText` (flutter/flutter#175787)
2025-09-24 47866232+chunhtai@users.noreply.github.com Fixes SemanticsFlags.isLink mis-translated in dart ui ffi (flutter/flutter#175812)
2025-09-24 1063596+reidbaker@users.noreply.github.com Update AGP/Java/Gradle comparison when using analyze --suggestions (flutter/flutter#175808)
2025-09-24 108678139+manu-sncf@users.noreply.github.com Fix SliverMainAxisGroup SliverEnsureSemantics support (flutter/flutter#175671)
2025-09-24 32538273+ValentinVignal@users.noreply.github.com Migrate to `WidgetStateColor` (flutter/flutter#175573)
2025-09-24 ahmedsameha1@gmail.com Make sure that a FlexibleSpaceBar doesn't crash in 0x0 environment (flutter/flutter#175228)
2025-09-24 engine-flutter-autoroll@skia.org Roll Fuchsia Test Scripts from BWj3yYC74ud58QhN0... to APSBP-sS-3FX69Ihf... (flutter/flutter#175944)
2025-09-24 ahmedsameha1@gmail.com Make sure that a MaterialApp doesn't crash in 0x0 environment (flutter/flutter#173090)
2025-09-24 36043466+koukibadr@users.noreply.github.com feat(cupertino): Add selectableDayPredicate parameter to CupertinoDatePicker for selectable day control #171332 (flutter/flutter#171334)
2025-09-24 mohellebiabdessalem@gmail.com Refactor `FlutterInjectorTest` to use lambdas/method reference (flutter/flutter#175777)
2025-09-24 mohellebiabdessalem@gmail.com Replace curly braces with lambdas in `KeyEventChannelTest` (flutter/flutter#175729)
2025-09-24 bkonyi@google.com [ Widget Preview ] Fix filter by file on Windows (flutter/flutter#175783)
2025-09-24 mohellebiabdessalem@gmail.com use lambda expressions /method reference to fix linter issue in `DartMessengerTest.java` (flutter/flutter#175733)
2025-09-24 engine-flutter-autoroll@skia.org Roll Packages from 3413b65 to 117bf63 (9 revisions) (flutter/flutter#175935)
2025-09-24 mohellebiabdessalem@gmail.com refactor code to use method reference and lambdas in `DartMessengerTest.java` (flutter/flutter#175731)
2025-09-24 mohellebiabdessalem@gmail.com Simplify/fix ordering of asserts in `TextInputPluginTest` (flutter/flutter#175784)
2025-09-24 mohellebiabdessalem@gmail.com Introduce a getter for `Project` to get `gradle-wrapper.properties` directly   (flutter/flutter#175485)
2025-09-24 mohellebiabdessalem@gmail.com Change the arguments order in `assertEquals` to fix linter issues (flutter/flutter#175719)
2025-09-24 42980667+srivats22@users.noreply.github.com Broken link in NavigationRail documentation (flutter/flutter#175852)
2025-09-24 mdebbar@google.com Updates to flutter web triage links (flutter/flutter#175791)
2025-09-24 jason-simmons@users.noreply.github.com Do not present textures in FlutterMetalLayer if the drawable size changed and the texture's size does not match the new drawable size (flutter/flutter#175450)
2025-09-24 bkonyi@google.com Remove comment about trailing commas from templates (flutter/flutter#175864)
2025-09-24 engine-flutter-autoroll@skia.org Roll Skia from 1c1b19f2ffc3 to 753ce2221ce7 (4 revisions) (flutter/flutter#175909)
2025-09-24 engine-flutter-autoroll@skia.org Roll Skia from 3191a822cf10 to 1c1b19f2ffc3 (2 revisions) (flutter/flutter#175896)
2025-09-24 engine-flutter-autoroll@skia.org Roll Skia from cabeab8cb22c to 3191a822cf10 (14 revisions) (flutter/flutter#175894)
2025-09-24 engine-flutter-autoroll@skia.org Roll Dart SDK from 14b4ced3022a to 899c7340cc4c (4 revisions) (flutter/flutter#175893)
2025-09-24 paulberry@google.com Roll `package:analyzer` forward to `8.2.0`. (flutter/flutter#175849)
2025-09-24 ahmedsameha1@gmail.com Make sure that a VerticalDivider doesn't crash at 0x0 environment (flutter/flutter#174761)
2025-09-24 ahmedsameha1@gmail.com Make sure that Drawer & DrawerHeader don't crash in 0x0 environment (flutter/flutter#174772)
2025-09-24 rmolivares@renzo-olivares.dev Add an assertion for the relationship between `Visibility.maintainState` and `Visibility.maintainFocusability` (flutter/flutter#175552)
2025-09-24 34465683+rkishan516@users.noreply.github.com fix: remove final class modifier on MenuController (flutter/flutter#174490)
2025-09-24 34465683+rkishan516@users.noreply.github.com fix: cupertino sheet broken example with programatic pop (flutter/flutter#175709)
2025-09-24 mdebbar@google.com [web] Fix assertion thrown when hot restarting during animation (flutter/flutter#175856)
2025-09-24 krca0220@gmail.com Add non uniform TableBorder (flutter/flutter#175773)
2025-09-23 mohellebiabdessalem@gmail.com fix small typo in test docs (flutter/flutter#175776)
2025-09-23 mohellebiabdessalem@gmail.com Use `assertNull` to simplify code (flutter/flutter#175720)

If this roll has caused a breakage, revert this CL and stop the roller
...
@EedupugantiVenkatesh

This comment was marked as off-topic.

engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 12, 2025
reidbaker pushed a commit to AbdeMohlbi/flutter that referenced this pull request Dec 10, 2025
…ePicker for selectable day control flutter#171332 (flutter#171334)

### Description

This PR enhances the CupertinoDatePicker by introducing a weekType
parameter, giving developers more control over which days users can
select.

### Solution

To address this, I've added a new weekType parameter to the
CupertinoDatePicker widget. This parameter offers a declarative way to
control the set of selectable days displayed in the picker, with options
defined in a new WeekType enum:

WeekType.workDays (Monday-Friday)

WeekType.weekends (Saturday-Sunday)

WeekType.fullWeek (all days, current default behavior)

WeekType.custom (allows developers to provide a List<int> representing
the DateTime.weekday values that should be visible and selectable).

### Example
```dart
// Example: Display only work days (Monday-Friday)
CupertinoDatePicker(
  mode: CupertinoDatePickerMode.date,
  initialDateTime: DateTime.now(),
  minimumDate: DateTime(2023, 1, 1),
  maximumDate: DateTime(2024, 12, 31),
  weekType: WeekType.workDays,
  onDateTimeChanged: (DateTime newDateTime) {
    // Handle date change
  },
);
```

### Screenshots


https://github.com/user-attachments/assets/8b1290c9-0d01-4199-921a-f86cd9d281a5


https://github.com/user-attachments/assets/e2bc4d6a-889e-4a47-89bc-535d7f57c04e


https://github.com/user-attachments/assets/475fa1e1-a56a-4a15-945d-890bb1ff51da


Here's the linked issue to this PR flutter#171332 

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Victor Sanni <victorsanniay@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants