Skip to content

[Text Scaling][Material] Update BottomNavigationBar to show tooltips on long press. - #59127

Merged
johnsonmh merged 30 commits into
flutter:masterfrom
johnsonmh:feature-bottomNavTextScaling
Aug 14, 2020
Merged

johnsonmh merged 30 commits into
flutter:masterfrom
johnsonmh:feature-bottomNavTextScaling

Conversation

@johnsonmh

@johnsonmh johnsonmh commented Jun 10, 2020 •

Copy link
Copy Markdown
Contributor

Description

This PR deprecates BottomNavigationBarItem.title, which is a Widget parameter, in favor of BottomNavigationBarItem.label, which is a String.

See full proposal: https://flutter.dev/go/bottom-navigation-bar-title-deprecation

Reasoning

Bottom Navigation Bars have limited space, so when the text scale factor increases, the text gets truncated.

Instead, the new Material guidance is to prevent the text in the bottom navigation bar from scaling, but then show tooltips on each item with the proper text scaling.

Before After
giphy-1 giphy-2

So, when BottomNavigationItem.label is used instead of BottomNavigationBar.title, the textScaleFactor of the bottom navigation component will be capped at 1.0, and a tooltip will be present on long press of the BottomNavigationBar.items.

Additionally, the BottomNavigationBar build method now asserts the presence of an Overlay ancestor, as this is required to show the tooltips.

Tests

I added the following tests:

  • Added a test to verify that tooltips are shown (with proper text scaling) on bottom nav items when labels are provided.
  • Added text scaling test to confirm that the bottom nav does not grow with text scale factor when labels are provided.
  • Updated the bottom nav semantics tests to reflect new semantics tree (with tooltip addition).
  • Added a test to the Cupertino BottomAppBar verifying that text is created when label param is used.

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.

@fluttergithubbot fluttergithubbot added p: material_ui material_ui package in flutter/packages framework flutter/packages/flutter repository. See also f: labels. labels Jun 10, 2020

@rami-a rami-a left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM but had one question and a few nits

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: Since this is only used once, maybe just inline it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed to:

    final MediaQueryData mediaQueryData = MediaQuery.of(context);
    return MediaQuery(
      // Do not grow text in bottom navigation bar because there is no room,
      // instead, properly scaled tooltips will show on long press.
      data: mediaQueryData.copyWith(
        textScaleFactor: math.min(1.0, mediaQueryData.textScaleFactor),
      ),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why is this needed? Wouldn't it be null to start with?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It needs to be explicitly initialized because it's a final field, but I don't want to expose it in this constructor.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same thing here, wouldn't message already be null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Same as above, it needs to be explicitly initialized (because it's a final field) and I don't want to expose it in this constructor.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would we only want the Tooltip if the text scale factor is greater than 1?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Guidance from design was to always include it, because it is useful for more than just text scale, for example when an item has no label.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I dont think you need this new line

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed.

@jonahwilliams
jonahwilliams self-requested a review June 10, 2020 21:14

@jonahwilliams jonahwilliams left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does this lose the semantics service announce if a Widget is provided to a tooltip?

@flutter-github-sync

Copy link
Copy Markdown

Started Google testing for this PR

@flutter-github-sync

Copy link
Copy Markdown

Google testing passed!

@goderbauer goderbauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not a full review, just the solution for the issue you mentioned in the chat.

Comment thread packages/flutter/lib/src/material/bottom_navigation_bar.dart Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

container: true can be removed here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

@goderbauer

Copy link
Copy Markdown
Member

What I noticed when playing around with this: the tooltip now also shows up when longpressing a Button in the Bar even when the textscale factor is "normal" and wouldn't require it. Is that expected?

@johnsonmh

Copy link
Copy Markdown
Contributor Author

@goderbauer Good question, yes that is intentional. The idea is that Tooltips provide value in more than just the text scaling case (say, when an item has no label at all), and having the behavior be consistent will help users learn that the tooltips will reliably be there on long press.

@flutter-github-sync

Copy link
Copy Markdown

Started Google testing for this PR

1 similar comment
@flutter-github-sync

Copy link
Copy Markdown

Started Google testing for this PR

@flutter-github-sync

Copy link
Copy Markdown

Google testing passed!

1 similar comment
@flutter-github-sync

Copy link
Copy Markdown

Google testing passed!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I hadn't really thought about this before in other contexts, but is there any advantage in scaling down the text if it already fits?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In this particular case, I believe that there are some users who are using textScaleFactor: 0 as a workaround to hide the labels, I do not want to break this use case. There was a period of time when BottomNavigationBar did not support hiding labels on the items.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: extra line

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why are 5 seconds needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

They weren't needed, changed to 2 seconds, which is what the tooltip uses (there needs to be some time for the tooltip to appear).

@rami-a rami-a left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe I'm just unfamiliar with these APIs but why do you call this in the constructor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

markNeedsSemanticsUpdate is what triggers assembleSemanticsNode to run, and as soon as this node is created, and I wanted to make sure that method gets called. I'm also loosely following the _RenderScrollSemantics example, which adds a listener to call markNeedsSemanticsUpdate in its constructor.

position.addListener(markNeedsSemanticsUpdate);

It's possible that this is unnecessary. @goderbauer Do you think this call is safe to remove?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems unnecessary. Newly created RenderObjects will always receive a semantics update when they first render (if semantics are turned on). What breaks if you remove this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe add a quick comment here explaining why we have this widget and what it does to the future reader.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems unnecessary. Newly created RenderObjects will always receive a semantics update when they first render (if semantics are turned on). What breaks if you remove this?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

assembleSemanticsNode only runs if semantics are turned on. Semantics are only turned on if an a11y service (e.g. TalkBack or VoiceOver) is running. I thought this label also needs to show if semantics are turned off? Based on that, I would expect that the tooltip is not showing a message when a11y services are turned off?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Side-note: For technical reasons, a11y are always turned on when running in a simulator. Did you try the tooltip thing on a real device without having any a11y services (outside of scaling the text) enabled? You may have to force-quit and restart the app after turning the a11y service off to delete the cached label.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe we should have a separate constructor for this new feature. It may be difficult to debug if you forget to specify the message and suddenly a random string from the semantics tree appears.

Comment thread packages/flutter/test/material/bottom_navigation_bar_test.dart Outdated
@fluttergithubbot fluttergithubbot added the p: cupertino_ui cupertino_ui package in flutter/packages label Jul 1, 2020
Comment thread packages/flutter/lib/src/widgets/bottom_navigation_bar_item.dart Outdated
Comment thread packages/flutter/lib/src/material/bottom_navigation_bar.dart Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this because of the overlay assert you added?

@johnsonmh johnsonmh Jul 7, 2020 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, exactly

@goderbauer goderbauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approach looks good.

Comment thread packages/flutter/lib/src/material/bottom_navigation_bar.dart Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should follow the deprecation style: https://github.com/flutter/flutter/wiki/Tree-hygiene#deprecation

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also: Can you update the doc comment on this to mention that this property is deprecated and link to the one that should be used instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done.

Based on the breaking change guide you sent, I also created this breaking change proposal: flutter.dev/go/bottom-navigation-bar-title-deprecation, it has been open to discussion for a ~week or so now.

@goderbauer

Copy link
Copy Markdown
Member

I saw you responded to the comments, but the code is still the old one. Did you by any chance forget to push? :)

@goderbauer goderbauer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@johnsonmh
johnsonmh force-pushed the feature-bottomNavTextScaling branch from dd0a2de to 3c2593e Compare August 13, 2020 20:39
@johnsonmh
johnsonmh merged commit bee9522 into flutter:master Aug 14, 2020
mingwandroid pushed a commit to mingwandroid/flutter that referenced this pull request Sep 6, 2020
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 14, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

c: contributor-productivity Team-specific productivity, code health, technical debt. framework flutter/packages/flutter repository. See also f: labels. p: cupertino_ui cupertino_ui package in flutter/packages p: material_ui material_ui package in flutter/packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants