-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Material Date Picker redesign #50546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Updated the showDatePicker() implementation to use the latest Material design UI.
rami-a
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks mostly good, comments are pretty minor but noticed a couple of small bugs when testing it out.
- Header overflows in landscape mode with text input and keyboard up
- Landscape mode should probably cap the width (especially in text input mode), otherwise it looks very wide.
- Rotating the device does not maintain the current month the user is viewing, it goes back to the initial month.
packages/flutter/lib/src/material/pickers/date_picker_deprecated.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/pickers/date_picker_header.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/pickers/date_picker_header.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/pickers/date_picker_header.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/pickers/calendar_date_picker.dart
Outdated
Show resolved
Hide resolved
packages/flutter/lib/src/material/pickers/calendar_date_picker.dart
Outdated
Show resolved
Hide resolved
…in state between orientation changes.
|
@rami-a, thanks for the review. I think I have either addressed all your feedback. There are some issues, like customizability which we will deal with in a DatePickerTheme pass in another PR.
These should all be fixed with my latest commits. Please let me know if you see anything else. |
| ), | ||
| ); | ||
|
|
||
| final Widget dialog = OrientationBuilder( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just return the OrientationBuilder here and not bother creating dialog at all?
| class _YearPickerState extends State<_YearPicker> { | ||
| ScrollController scrollController; | ||
|
|
||
| // The approximate number of years necessary to fill the available space. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this a little more? Why is it approximate, not exact, and what available space is it filling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure :). This was code from @rami-a that I didn't look that closely at. I'll spend some time with it and see if I can get better docs here and your next comment below.
| void initState() { | ||
| super.initState(); | ||
|
|
||
| // Set the scroll position to approximately center the initial year. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, why approximate, and when does the approximation get resolved? Is there some kind of step that narrows down the value to the exact value?
| /// calendar date picker initially appear in the [DatePickerMode.year] or | ||
| /// [DatePickerMode.day] mode. It defaults to [DatePickerMode.day], and | ||
| /// must be non-null. | ||
| /// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra line can be removed.
| case DatePickerEntryMode.calendar: | ||
| _entryMode = DatePickerEntryMode.input; | ||
| break; | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: don't need the extra line here, IMO.
HansMuller
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly small stuff and wordsmithing.
| /// This applies the leap year logic introduced by the Gregorian reforms of | ||
| /// 1582. It will not give valid results for dates prior to that time. | ||
| int _getDaysInMonth(int year, int month) { | ||
| const List<int> daysInMonth = <int>[31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could move this declaration below the Feb expression
|
|
||
| /// The text that is displayed at the center of the header. | ||
| /// | ||
| /// This will display the selected date in large typography. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it displayed in in [titleStyle]?
|
|
||
| /// Re-usable widget that displays the selected date (in large font) and the | ||
| /// help text above it. | ||
| /// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When reading classes like this it's necessary to remember that they're essentially "package private", they're not exported to the material library. Maybe add a boilerplate comment to that effect?
| /// The returned [Future] resolves to the date selected by the user when the | ||
| /// user confirms the dialog. If the user cancels the dialog, null is returned. | ||
| /// | ||
| /// The [initialDate] is the initially shown and selected date in the picker. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentence is a little hard to parse.
Maybe something like: When the date picker is first displayed, [initialDate] is selected.
| /// * [cancelText], label on the cancel button. | ||
| /// * [confirmText], label on the ok button. | ||
| /// * [errorFormatText], message used when the input text isn't in a proper date format. | ||
| /// * [errorInvalidText], message used when the input date isn't a selectable date. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
input date => input text
packages/flutter/lib/src/material/pickers/date_picker_dialog.dart
Outdated
Show resolved
Hide resolved
| final MaterialLocalizations localizations = MaterialLocalizations.of(context); | ||
| final Orientation orientation = MediaQuery.of(context).orientation; | ||
| final TextTheme textTheme = theme.textTheme; | ||
| final double textScaleFactor = math.min(MediaQuery.of(context).textScaleFactor, 1.3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably merits a brief explanation
| ? colorScheme.onPrimary | ||
| : colorScheme.onSurface; | ||
| final TextStyle dateStyle = orientation == Orientation.landscape | ||
| ? textTheme.headline5?.apply(color: dateColor) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as elsewhere about apply instead of copyWith
- Minor documentation fixes - Switching to copyWith instead of apply for text styles - Optimization in getDaysInMonth
- Simplified the dialog build method. - Replaced the Transform widget with a RotationTransition widget for the year/day mode drop down arrow animation.
… the _MonthPicker to cleanup the controller handling.
Thanks for the review @HansMuller. Can you take another look with my latest commits? |
HansMuller
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
Thanks for this great PR, @darrenaustin! For our web app we are on master channel. Yesterday we pushed a new web app update and today we received the first user feedbacks that they love the new date picker 😍 https://web.sharezone.net |
|
Pls is the new material date picker available for use on flutter now? Do I need to update my current flutter version? |
| text: filteredValue.text.replaceAll(RegExp(r'[\D]'), separator), | ||
| ); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@darrenaustin I'm about to check in something that replaces WhitelistingTextInputFormatter and BlacklistingTextInputFormatter with a single FilteringTextInputFormatter that handles replacement even for the case of allow-list filtering, which you might be able to use here.
| // NOTE: This is an internal implementation file. Even though there are public | ||
| // classes and functions defined here, they are only meant to be used by the | ||
| // date picker implementation and are not exported as part of the Material library. | ||
| // See pickers.dart for exactly what is considered part of the public API. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a general rule, we should just export everything and support everything as a public API. The reality is that everyone can see everything we do, so they'll just import the files directly if they want to, so we have to consider everything public anyway. I think we should just make everything public rather than start having semi-private APIs like this.
| import '../text_theme.dart'; | ||
| import '../theme.dart'; | ||
|
|
||
| // NOTE: This is an internal implementation file. Even though there are public |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
trivial nit: "NOTE" is against our style guide. :-)

Description
The design for the Material Date Picker has been updated:
https://material.io/components/pickers/#mobile-pickers
This PR updates Flutter's implementation to match the new design.
In addition to just updating the visuals and controls, a new text input mode was added to the dialog as per the design.
The API changes are documented at: https://flutter.dev/go/material-date-picker-redesign
Note that this does not include support for the Date Range picker as that will be coming in a future PR.
Also, credit to @rami-a who implemented a similar internal design that I based this on. However, any problems were introduced by me, so don't blame him :).
Related Issues
Tests
The tests in
date_picker_test.darthave been updated to test the new UI implementation. Tests for the new text input mode were also added to cover that.Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.