Unverified Commit 2b7b4bdc authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix an exception being thrown when focus groups are empty. (#86734)

When a focus traversal group has no entries, but traversal is requested, we were throwing an exception because we couldn't find the group marker's scope in the list of candidates. This fixes that, and adds a test.
parent 94f71f37
......@@ -314,7 +314,6 @@ abstract class FocusTraversalPolicy with Diagnosticable {
}
// Sort the member lists using the individual policy sorts.
final Set<FocusNode?> groupKeys = groups.keys.toSet();
for (final FocusNode? key in groups.keys) {
final List<FocusNode> sortedMembers = groups[key]!.policy.sortDescendants(groups[key]!.members, currentNode).toList();
groups[key]!.members.clear();
......@@ -326,7 +325,7 @@ abstract class FocusTraversalPolicy with Diagnosticable {
final List<FocusNode> sortedDescendants = <FocusNode>[];
void visitGroups(_FocusTraversalGroupInfo info) {
for (final FocusNode node in info.members) {
if (groupKeys.contains(node)) {
if (groups.containsKey(node)) {
// This is a policy group focus node. Replace it with the members of
// the corresponding policy group.
visitGroups(groups[node]!);
......@@ -336,8 +335,10 @@ abstract class FocusTraversalPolicy with Diagnosticable {
}
}
// Visit the children of the scope.
visitGroups(groups[scopeGroupMarker?.focusNode]!);
// Visit the children of the scope, if any.
if (groups.isNotEmpty && groups.containsKey(scopeGroupMarker?.focusNode)) {
visitGroups(groups[scopeGroupMarker?.focusNode]!);
}
// Remove the FocusTraversalGroup nodes themselves, which aren't focusable.
// They were left in above because they were needed to find their members
......
......@@ -2015,6 +2015,14 @@ void main() {
expect(events.length, 2);
});
testWidgets('Focus traversal does not throw when no focusable is available in a group', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(home: Scaffold(body: ListTile(title: Text('title')))));
final FocusNode? initialFocus = primaryFocus;
await tester.sendKeyEvent(LogicalKeyboardKey.tab);
await tester.pump();
expect(primaryFocus, equals(initialFocus));
});
testWidgets('Focus traversal does not break when no focusable is available on a WidgetsApp', (WidgetTester tester) async {
final List<RawKeyEvent> events = <RawKeyEvent>[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment