Skip to content

Commit e6a65af

Browse files
authored
Directional focus edge traversal behavior. (flutter#161285)
Fixes: flutter#160843 This PR adds edge behavior feature for traversing focus using arrow keys. This allows cycling through the focus within the `FocusScope` in a closed loop using the arrow keys. Which may be needed by TV application developers. Additionally, as in case flutter#160843, `TraversalEdgeBehavior.parentScope` can be used to allow nested Navigators to traverse focus beyond the Navigator using arrow keys. ```dart MaterialApp( home: Column( children: <Widget>[ makeFocus(0), Navigator( onGenerateRoute: (RouteSettings settings) { return MaterialPageRoute<void>( traversalDirectionedEdgeBehavior: TraversalEdgeBehavior.parentScope, builder: (BuildContext context) { return Column( children: <Widget>[ makeFocus(1), makeFocus(2), ], ); }, ); }, ), makeFocus(3), ], ), ); ``` ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent f039697 commit e6a65af

File tree

9 files changed

+696
-130
lines changed

9 files changed

+696
-130
lines changed

packages/flutter/lib/src/material/page.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ class MaterialPageRoute<T> extends PageRoute<T> with MaterialRouteTransitionMixi
4242
super.fullscreenDialog,
4343
super.allowSnapshotting = true,
4444
super.barrierDismissible = false,
45+
super.traversalEdgeBehavior,
46+
super.directionalTraversalEdgeBehavior,
4547
}) {
4648
assert(opaque);
4749
}

packages/flutter/lib/src/widgets/focus_manager.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,6 +1358,7 @@ class FocusScopeNode extends FocusNode {
13581358
super.skipTraversal,
13591359
super.canRequestFocus,
13601360
this.traversalEdgeBehavior = TraversalEdgeBehavior.closedLoop,
1361+
this.directionalTraversalEdgeBehavior = TraversalEdgeBehavior.stop,
13611362
}) : super(descendantsAreFocusable: true);
13621363

13631364
@override
@@ -1374,6 +1375,13 @@ class FocusScopeNode extends FocusNode {
13741375
/// and apply the new behavior.
13751376
TraversalEdgeBehavior traversalEdgeBehavior;
13761377

1378+
/// Controls the directional transfer of focus when the focus is on the first or last item.
1379+
///
1380+
/// Changing this field value has no immediate effect on the UI. Instead, next time
1381+
/// focus traversal takes place [FocusTraversalPolicy] will read this value
1382+
/// and apply the new behavior.
1383+
TraversalEdgeBehavior directionalTraversalEdgeBehavior;
1384+
13771385
/// Returns true if this scope is the focused child of its parent scope.
13781386
bool get isFirstFocus => enclosingScope!.focusedChild == this;
13791387

0 commit comments

Comments
 (0)