Skip to content

Add OrderedFocusTraversalPolicy and FocusTraversalGroup to allow focus traversal to follow a predefined order.#49235

Merged
gspencergoog merged 24 commits intoflutter:masterfrom
gspencergoog:ordinal_focus
Feb 11, 2020
Merged

Add OrderedFocusTraversalPolicy and FocusTraversalGroup to allow focus traversal to follow a predefined order.#49235
gspencergoog merged 24 commits intoflutter:masterfrom
gspencergoog:ordinal_focus

Conversation

@gspencergoog
Copy link
Copy Markdown
Contributor

@gspencergoog gspencergoog commented Jan 21, 2020

Description

This change adds a way to provide explicit focus order for a part of the widget tree.

It adds FocusTraversalPolicyGroup, which in many ways is similar to DefaultFocusTraversal, except that it groups a widget subtree together so that those nodes are traversed as a group. DefaultFocusTraversal doesn't work as one would expect: If there is more than one DefaultFocusTraversal inside of a focus scope, the policy can change depending on which node was asked to move "next", which can cause unexpected behavior. The new grouping mechanism doesn't have that problem. I deprecate DefaultFocusTraversal in this PR.

It adds OrderedFocusTraversalPolicy, which is a policy that can be supplied to FocusTraversalPolicyGroup to set the policy for a sub-tree. It looks for FocusTraversalOrder inherited widgets, which use a FocusOrder to do the sorting. FocusOrder has two subclasses: NumericalFocusOrder (which sorts based on a double), and LexicalFocusOrder, which sorts based on a String.

As part of doing this, I refactored the way FocusTraversalPolicy is implemented so that it has more default implementation methods, and exposes a new protected member: sortDescendants, which makes it easier for developers to make their own policy subclasses: they only need to implement sortDescendants to get a new ordering behavior, but can also still override any of the default implementation behaviors if they need different behavior.

I was able to do this without breaking the API (AFAICT).

Related Issues

Tests

  • Added tests for new traversal policy and the different types of *Order classes.

Breaking Change

  • No, this is not a breaking change.

@fluttergithubbot fluttergithubbot added f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels Jan 21, 2020
@domesticmouse
Copy link
Copy Markdown
Contributor

PTAL @redbrogdon

@gspencergoog gspencergoog changed the title Ordinal focus Add OrderedFocusTraversalPolicy to allow focus traversal to follow a predefined order. Jan 22, 2020
@goderbauer
Copy link
Copy Markdown
Member

nit: the analyzer is mad about some white space.

@gspencergoog
Copy link
Copy Markdown
Contributor Author

That analyzer is so picky, picky, picky! :-) (removed whitespace).

Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/lib/src/widgets/focus_traversal.dart Outdated
Comment thread packages/flutter/test/widgets/focus_traversal_test.dart Outdated
@goderbauer
Copy link
Copy Markdown
Member

From looking at the code it wasn't immediately clear to me if you could mix and match different policies. Let's say I am using a (third-party) widget that is internally managing FocusOrder via the lexical order and I want to use that widget in my app where I generally manage focus order with numerical order. Can I do that? How? Might be worthwhile to have a test.

Same for different non-OrderedFocusTraversalPolicy in different subtrees.

@gspencergoog gspencergoog force-pushed the ordinal_focus branch 4 times, most recently from 088c1ca to 096fb6f Compare January 24, 2020 16:20
@gspencergoog gspencergoog changed the title Add OrderedFocusTraversalPolicy to allow focus traversal to follow a predefined order. Add OrderedFocusTraversalPolicy and FocusTraversalPolicyGroup to allow focus traversal to follow a predefined order. Jan 24, 2020
@goderbauer
Copy link
Copy Markdown
Member

The analyzer is complaining about a dependency loop.

@gspencergoog gspencergoog changed the title Add OrderedFocusTraversalPolicy and FocusTraversalPolicyGroup to allow focus traversal to follow a predefined order. Add OrderedFocusTraversalPolicy and FocusTraversalGroup to allow focus traversal to follow a predefined order. Jan 24, 2020
@gspencergoog gspencergoog force-pushed the ordinal_focus branch 4 times, most recently from e172b4b to 077bc81 Compare January 27, 2020 21:14
@gspencergoog
Copy link
Copy Markdown
Contributor Author

OK, @goderbauer, I think this is ready for another look.

@goderbauer
Copy link
Copy Markdown
Member

I am still a little concerned about the performance implications of this.

Ignoring that, this LGTM.

@goderbauer
Copy link
Copy Markdown
Member

Looks like Cirrus is unhappy now, though.

@gspencergoog gspencergoog merged commit 8ef5e2f into flutter:master Feb 11, 2020
@gspencergoog gspencergoog deleted the ordinal_focus branch February 11, 2020 17:18
gspencergoog added a commit to gspencergoog/flutter that referenced this pull request Feb 12, 2020
…l… (flutter#49235)"

This reverts commit 8ef5e2f because it breaks some semantics tests.
gspencergoog added a commit that referenced this pull request Feb 13, 2020
This re-lands #49235 with the addition of includeSemantics flag on the Focus widget so that the FocusTraversalGroup can create a Focus widget without affecting the semantics tree.

The FocusTraversalGroup uses the Focus widget to create a grouping of descendants for traversal, but doesn't actually participate in focus (canRequestFocus is always false), so we don't want it to add a Semantics widget in that case, since that can cause semantics changes. The canRequestFocus attribute can also be used when a widget is disabled, so we do sometimes want to include Semantics even if that is false, but not in the case where it is always false, as for FocusTraversalGroup.

- Added a test to make sure that FocusTraversalGroup doesn't add any semantics information.
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 1, 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. 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.

6 participants