Skip to content

Conversation

@darrenaustin
Copy link
Contributor

@darrenaustin darrenaustin commented Feb 11, 2020

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.

DatePickerM2

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.dart have 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.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Did any tests fail when you ran them? Please read Handling breaking changes.

  • No, no existing tests failed, so this is not a breaking change.

@fluttergithubbot fluttergithubbot added a: internationalization Supporting other languages or locales. (aka i18n) f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. c: contributor-productivity Team-specific productivity, code health, technical debt. labels Feb 11, 2020
@flutter flutter deleted a comment from googlebot Feb 28, 2020
@flutter flutter deleted a comment from googlebot Feb 28, 2020
Updated the showDatePicker() implementation to use the latest Material design UI.
@darrenaustin darrenaustin changed the title WIP: Date picker redesign Material Date Picker redesign Mar 3, 2020
Copy link
Contributor

@rami-a rami-a left a 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.

@darrenaustin
Copy link
Contributor Author

@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.

  • 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.

These should all be fixed with my latest commits. Please let me know if you see anything else.

),
);

final Widget dialog = OrientationBuilder(
Copy link
Contributor

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.
Copy link
Contributor

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?

Copy link
Contributor Author

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.
Copy link
Contributor

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.
///
Copy link
Contributor

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;

Copy link
Contributor

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.

Copy link
Contributor

@HansMuller HansMuller left a 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];
Copy link
Contributor

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.
Copy link
Contributor

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.
///
Copy link
Contributor

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.
Copy link
Contributor

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.
Copy link
Contributor

Choose a reason for hiding this comment

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

input date => input text

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);
Copy link
Contributor

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)
Copy link
Contributor

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.
@darrenaustin
Copy link
Contributor Author

Mostly small stuff and wordsmithing.

Thanks for the review @HansMuller. Can you take another look with my latest commits?

@darrenaustin darrenaustin requested a review from HansMuller March 20, 2020 21:55
Copy link
Contributor

@HansMuller HansMuller left a comment

Choose a reason for hiding this comment

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

LGTM

@Hixie
Copy link
Contributor

Hixie commented Mar 24, 2020

Do we know if this will address #49809 or #49810?

@darrenaustin darrenaustin merged commit 142b526 into flutter:master Mar 25, 2020
@darrenaustin darrenaustin deleted the date_picker_redux branch March 25, 2020 01:45
@darrenaustin
Copy link
Contributor Author

Do we know if this will address #49809 or #49810?

Unfortunately, this PR will not address those. They are still on my list. After I land the date range picker I will update them to address #49809. The Time Picker is currently being update by @rami-a and we can look at #49810 after he is finished with that.

@nilsreichardt
Copy link
Contributor

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 😍

image

https://web.sharezone.net

@ilechcod
Copy link

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),
);
}
}
Copy link
Contributor

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.
Copy link
Contributor

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
Copy link
Contributor

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. :-)

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: internationalization Supporting other languages or locales. (aka i18n) c: contributor-productivity Team-specific productivity, code health, technical debt. 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.

Material design component: mobile date input picker