Skip to content
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

Update the cupertino picker visuals #65501

Merged
merged 46 commits into from Oct 7, 2020

Conversation

YeungKC
Copy link
Member

@YeungKC YeungKC commented Sep 9, 2020

Description

The following changes were made to update to an iOS 14 style picker:
Update tertiarySystemFill (That's a mistake, It's been resolved.)
Update pickerTextStyle default letterSpacing
Adding magnifier parameters to the CupertinoPicker constructor method
Update the default magnifier default style
Updates magnifier styles for CupertinoDatePicker and CupertinoTimerPicker.
Tests Related to Modifying CupertinoPicker Styles

Compare with native visuals:
picker

The CupertinoDatePicker and CupertinoTimerPicker tests still fail, and I still don't understand the similarity between the

matchesGoldenFile('date_picker_test.datetime.initial.png')

The operating principle of the test is modified in order to pass the test.

Related Issues

Fixes #63694

Tests

I added the following tests:

Replace this with a list of the tests that you added as part of this PR. A change in behavior with no test covering it
will likely get reverted accidentally sooner or later. PRs must include tests for all changed/updated/fixed behaviors. See Test Coverage.

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.

@flutter-dashboard flutter-dashboard bot added f: cupertino flutter/packages/flutter/cupertino repository framework flutter/packages/flutter repository. See also f: labels. labels Sep 9, 2020
darkElevatedColor: Color.fromARGB(61, 118, 118, 128),
highContrastElevatedColor: Color.fromARGB(51, 118, 118, 128),
darkHighContrastElevatedColor: Color.fromARGB(81, 118, 118, 128),
color: Color.fromRGBO(118, 118, 128, 0.12),
Copy link
Member

Choose a reason for hiding this comment

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

Are these the same values as the ARGB variant?

Copy link
Member Author

Choose a reason for hiding this comment

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

At your reminder, I rechecked this part of the color and found that in fact the color I got from the capture view hierarchy converted and matched the original color, which was my error and is now resolved.

@@ -58,6 +58,22 @@ void _animateColumnControllerToItem(FixedExtentScrollController controller, int
);
Copy link
Member

Choose a reason for hiding this comment

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

Can you attach a screenshot for the date picker to help review as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

Simulator Screen Shot - iPhone 11 - 2020-09-10 at 14 55 35

This is what the CupertinoDatePicker looks like in action, as iOS has removed this style, so it can't be compared to native components.

Copy link
Member

Choose a reason for hiding this comment

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

You can by picking wheels in xcode. But it's definitely not very obvious.

Screen Shot 2020-09-10 at 3 58 28 PM

@@ -80,7 +80,7 @@ const TextStyle _kDefaultPickerTextStyle = TextStyle(
fontFamily: '.SF Pro Display',
fontSize: 21.0,
fontWeight: FontWeight.w400,
letterSpacing: -0.41,
letterSpacing: -0.6,
Copy link
Member

Choose a reason for hiding this comment

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

Can you add a description on how you derived this value? This will help the next maintainer assess his confidence on whether that person is more rigorous or less than you are :)

e.g. extracted from Apple sketch specs or compared visually etc.

Copy link
Member Author

Choose a reason for hiding this comment

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

To do this, I've made two comparison images that overlap the native text style version and the flutter text new and old style version, respectively.

This is a comparison of native and old version:
old

This is a comparison of native and new version:
new

It doesn't look like much of a difference, but the new style version will be a little more accurate.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds good, I meant could you modify the code comment above this const declaration? It'll leave some hints for the next maintainer.

Copy link
Member Author

Choose a reason for hiding this comment

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

Maybe I'll add a comment:

// LetterSpacing sourced from iOS 14 simulator screenshots for comparison.
See also:
//
// * https://github.com/flutter/flutter/pull/65501#discussion_r486557093

What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

For code comments, it's ok. (I wouldn't reference /// docs to ephemeral discussions like GitHub PRs).

Copy link
Member Author

Choose a reason for hiding this comment

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

It's updated now.

Copy link
Contributor

@LongCatIsLooong LongCatIsLooong left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thank you for the PR!

Not sure why there's no untriaged digest showing up on https://flutter-gold.skia.org/. Maybe the website needs time to catch up, I'll check again tomorrow.

const BorderRadius _rightBorderRadius = BorderRadius.horizontal(right: Radius.circular(CupertinoPicker.defaultHighlighterRadius));


Container _buildMagnifier(BuildContext context, [EdgeInsetsGeometry margin = EdgeInsets.zero, BorderRadiusGeometry borderRadius = BorderRadius.zero]) => Container(
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we should expose this builder (or expose another constructor in CupertinoPicker that allows developers to specify which side of the magnifier should have rounded corners and non-zero margins), so people can build their own multi-column pickers with ease?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

I thought about doing this, but might it be easier to customize the style by providing the magnifier parameters directly?
If satisfied with the convenience of creating multi-column pickers, perhaps we could create a CupertinoPickerDefaulMagnifier StatelessWidget?
What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah having a widget for that sounds good to me, with it we can make the margin/radius constants private.

Copy link
Member Author

Choose a reason for hiding this comment

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

The CupertinoPickerDefaultMagnifier has now been created.

@@ -193,6 +190,15 @@ class CupertinoPicker extends StatefulWidget {
/// A delegate that lazily instantiates children.
final ListWheelChildDelegate childDelegate;

/// the [magnifier] widget overlaid on top of [ListWheelScrollView].
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe mention that the [magnifier] will be vertically centered and have the same size as the magnified centered item, and defaults to the grey rrect first introduced in iOS 14.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, I'm not very good at English, thanks for the advice.

Copy link
Member Author

Choose a reason for hiding this comment

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

Do you think it's okay if I change it to this?

  /// The [magnifier] widget overlaid on top of [ListWheelScrollView],
  /// it will be vertically centered and will be the same size as the magnified item,
  /// defaulting to the grey rrect first introduced in iOS 14.

offAxisFraction = -_kMaximumOffAxisFraction * textDirectionFactor;
else if (i >= 2 || columnWidths.length == 2)
magnifier = _buildMagnifier(context, _leftEdgeInsets, _leftBorderRadius);
} else
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: else if should be on the same line?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's my formatting omission, thank you.

@xster
Copy link
Member

xster commented Sep 10, 2020

oh https://github.com/flutter/flutter/wiki/Writing-a-golden-file-test-for-package:flutter#first-time-contributors it looks like there's a special step for first time contributors. cc @Piinks

Copy link
Member

@xster xster left a comment

Choose a reason for hiding this comment

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

This is a very clean fix. Thank you @YeungKC!

Just a few more comments. Generally, I'd rename magnifier to selectionOverlay everywhere (since we don't know if useMagnifier is true and what users are going to put in there).

Once address, let's wait for the golden image to come in, then we can merge.

@@ -80,7 +80,7 @@ const TextStyle _kDefaultPickerTextStyle = TextStyle(
fontFamily: '.SF Pro Display',
fontSize: 21.0,
fontWeight: FontWeight.w400,
letterSpacing: -0.41,
letterSpacing: -0.6,
Copy link
Member

Choose a reason for hiding this comment

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

Sounds good, I meant could you modify the code comment above this const declaration? It'll leave some hints for the next maintainer.

Comment on lines 193 to 195
/// The [magnifier] widget overlaid on top of [ListWheelScrollView],
/// it will be vertically centered and will be the same size as the magnified item,
/// default to use [CupertinoPickerDefaultMagnifier].
Copy link
Member

Choose a reason for hiding this comment

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

A widget overlaid on the picker to highlight the currently selected entry.

The [selectionOverlay] widget drawn above the [CupertinoPicker]'s picker wheel. 
It is vertically centered in the picker and is constrained to have the same height as the
center row. 

If unspecified, it defaults to a [CupertinoPickerDefaultMagnifier] which is a gray 
rounded rectangle overlay in the iOS 14 style. 

Word wrap as needed. In general, documentation need a 1 line summary (which is what appears when you hover over a field in IDEs' popup hints).

I wouldn't mention ListWheelScrollView here since it's an implementation detail of this API and users probably won't know what it is.

/// The [magnifier] widget overlaid on top of [ListWheelScrollView],
/// it will be vertically centered and will be the same size as the magnified item,
/// default to use [CupertinoPickerDefaultMagnifier].
final Widget magnifier;
Copy link
Member

Choose a reason for hiding this comment

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

I'd rename this selectionOverlay. A 'magnifier' is what it does, not what it is. We don't know what it's going to do if the user is free to specify anything they want here.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you, I've solved this now.

@@ -125,6 +121,7 @@ class CupertinoPicker extends StatefulWidget {
@required this.onSelectedItemChanged,
@required IndexedWidgetBuilder itemBuilder,
int childCount,
this.magnifier,
Copy link
Member

Choose a reason for hiding this comment

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

The general pattern is to have a default value here (e.g. this.magnifier = const CupertinoPickerDefaultMagnifier()) rather than filling it in in the state. This way, you can actually specify null as an intended value (to not draw anything there if users want).

Copy link
Member Author

Choose a reason for hiding this comment

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

This was my mistake, thank you, and is now resolved.

Copy link
Member

Choose a reason for hiding this comment

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

It's not a mistake :) We didn't really document this pattern clearly.

Copy link
Member Author

Choose a reason for hiding this comment

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

But this is a best way.

@@ -313,6 +310,57 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
}
}

/// An picker default magnifier, grey rrect first introduced in iOS 14
Copy link
Member

Choose a reason for hiding this comment

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

A default selection overlay for [CupertinoPicker]s.

It draws a gray rounded rectangle to match the picker visuals introduced in iOS 14

Copy link
Member Author

Choose a reason for hiding this comment

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

Thank you, it's updated now.

/// An picker default magnifier, grey rrect first introduced in iOS 14
class CupertinoPickerDefaultMagnifier extends StatelessWidget {

/// Create a magnifier, it can be easily configured with the default style.
Copy link
Member

Choose a reason for hiding this comment

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

Don't editorialize or use subjective adjectives. Just state what it does.

Copy link
Member Author

Choose a reason for hiding this comment

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

The api doc has been updated and has a more detailed description of the arguments.

/// The color to fill in the background of the magnifier, Support for using [CupertinoDynamicColor].
final Color background;

/// default margin of the 'magnifier'.
Copy link
Member

Choose a reason for hiding this comment

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

Use complete sentences for all documentations (e.g. capitalize first letter).

Copy link
Member Author

Choose a reason for hiding this comment

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

That was my mistake and it's now resolved.

const CupertinoPickerDefaultMagnifier({
Key key,
this.background = CupertinoColors.tertiarySystemFill,
this.useLeftStyle = true,
Copy link
Member

Choose a reason for hiding this comment

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

Could be more self-descriptive. Maybe capLeftEdge?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a good name, I've been thinking about naming it for a long time.... Thank you! ~~ It's been updated now.

@@ -453,7 +457,7 @@ class CupertinoDatePicker extends StatefulWidget {
}
}

typedef _ColumnBuilder = Widget Function(double offAxisFraction, TransitionBuilder itemPositioningBuilder);
typedef _ColumnBuilder = Widget Function(double offAxisFraction, TransitionBuilder itemPositioningBuilder, Widget magnifier);
Copy link
Member

Choose a reason for hiding this comment

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

You missed these names here (magnifier -> selectionOverlay)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, thanks for reminding me.

@@ -982,17 +990,23 @@ class _CupertinoDatePickerDateTimeState extends State<CupertinoDatePicker> {

for (int i = 0; i < columnWidths.length; i++) {
double offAxisFraction = 0.0;
if (i == 0)
Widget magnifier;
Copy link
Member

Choose a reason for hiding this comment

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

I'd do a comb for the rename everywhere

@YeungKC
Copy link
Member Author

YeungKC commented Sep 28, 2020

image

Before I updated, I found out about TimerPicker golden tests missing the default fontSize value, so I got unexpected results.
This has now been updated, and I get the expected results.

btw, in the original test, the local test couldn't output the gold file, but here it does: https://flutter-gold.skia.org/detail?test=cupertino.timer_picker_test.datetime.initial&digest=ff6ad81d5189b693156e3501a20a5d7f

@xster
Copy link
Member

xster commented Sep 29, 2020

@YeungKC
Copy link
Member Author

YeungKC commented Sep 29, 2020

I know, but I'm not sure why it's not the same as my local test results and if I can re-run the test generation?

@xster
Copy link
Member

xster commented Oct 2, 2020

Sorry that this process is taking longer with the tests. Let us poke at it a bit more for a day. If we can't figure it out, I'll ask you to remove the TimerPicker golden tests test from date_picker_test.dart and we'll go figure it out afterwards. The PR itself is great and the test issue here isn't caused by you as far as I can tell.

@YeungKC
Copy link
Member Author

YeungKC commented Oct 2, 2020

Thank you for your follow-up, I believe this is worth the wait.

Copy link
Contributor

@Piinks Piinks left a comment

Choose a reason for hiding this comment

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

@xster it looks like you triaged the images on https://flutter-gold.skia.org/triagelog, can you confirm that's all good? :)
I do not know why the Cirrus framework_tests-libraries-linux is showing a strange golden failure, I think there is another infra issue there, looking into it now.
The Linux web-tests look to be timing out due to #67454

@xster
Copy link
Member

xster commented Oct 6, 2020

It's still off I think but I couldn't figure out the current state.

Looking at
Screen Shot 2020-10-06 at 3 19 31 PM
no new commits appeared under the same PR. There's 45 here and 29 there. The main issues we were facing were the cupertino.timer_picker_test.datetime goldens. I marked the last known incorrect ones as negative. Though it seems like we never triggered new ones for me to be able to triage on newer commits since.

@Piinks
Copy link
Contributor

Piinks commented Oct 6, 2020

Have you tried running it locally since the local execution was fixed?
Not every commit is tested (like when I push 3 commits, only the latest gets tested), so I think that is why the # of commits is not matching with your accounting.

@xster
Copy link
Member

xster commented Oct 7, 2020

ya the local results are as expected.

@YeungKC could I ask you to just comment out the 'TimerPicker golden tests' in the date_picker_test.dart file? I locally validated that the layout and rendering is correct and various widths didn't overflow. I'll poke at the golden test after you merge your changes to turn it back on.

@Piinks
Copy link
Contributor

Piinks commented Oct 7, 2020

The cirrus failure is due to #67463, fix is in #67468
Sorry for the infra issues. Our migration to luci has caused a lot of gold issues lately.

@fluttergithubbot
Copy link
Contributor

This pull request is not suitable for automatic merging in its current state.

  • The status or check suite framework_tests-libraries-linux has failed. Please fix the issues identified (or deflake) before re-applying this label.

@xster
Copy link
Member

xster commented Oct 7, 2020

@Piinks don't know if it's related to #67468. The tests are indicating a date_picker_test.datetime.initial failure though in the gold console, I already approved the new image

Screen Shot 2020-10-07 at 10 46 59 AM

Maybe there's some cross-talk with Cirrus as you're pointing out.

@YeungKC could you comment out 'DatePicker golden tests' as well? Sorry for the hassle so far. I'll turn them back on after we unblock this PR.

@Piinks
Copy link
Contributor

Piinks commented Oct 7, 2020

@Piinks don't know if it's related to #67468. The tests are indicating a date_picker_test.datetime.initial failure though in the gold console, I already approved the new image

It is related. The failure you are seeing here has nothing to do with the dashboard, that all looks to be ok.

Screen Shot 2020-10-07 at 12 54 20 PM

This is a Cirrus failure. Cirrus is no longer talking to Gold, so it is failing here without a way to be resolved.

Screen Shot 2020-10-07 at 10 46 59 AM

This image shows only luci builds in the parameters under CI. That looks to be as expected.

The cirrus build failure here can't be resolved until #67468 lands and can be patched in. An infra change added a Cirrus build without the config to talk to Gold, so it is stuck right now.

@xster
Copy link
Member

xster commented Oct 7, 2020

@YeungKC sorry, I just understood what @Piinks was saying. There are 2 testing infrastructures in transition and both are running golden though only 1 is the "source of truth". Linux framework_tests have already been passing for a while. That's the one appearing in the gold console. framework_tests-libraries-linux is now the deprecated infrastructure and no longer matters. We don't have to comment out more tests :). I'll merge this PR shortly after the last test completes.

@xster
Copy link
Member

xster commented Oct 7, 2020

Confirming both the rob test and the cirrus test are non-blockers. The rob test looped in files in the CL that aren't part of this PR due to merge issues. And the cirrus test is extraneous since the golden tests already ran on luci as mentioned above. Merging and then I'll turn the skipped golden back on. Thanks for your contribution and your patience on this one @YeungKC!

@xster xster merged commit db25441 into flutter:master Oct 7, 2020
jonahwilliams added a commit that referenced this pull request Oct 7, 2020
@YeungKC
Copy link
Member Author

YeungKC commented Oct 8, 2020

This is my first pr, but I underestimated the scope of changes and code requirements. I really thank you all for your patience during this process, and I have grown from it.

@xster @LongCatIsLooong @Piinks

@xster
Copy link
Member

xster commented Oct 9, 2020

Thanks for working through it too and being responsive. This is a high quality PR. Sorry for the infra issues. We're working through a migration so there's some wrinkles. Hopefully it won't happen again on your next PR :D

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 framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update the Cupertino picker visuals
7 participants