[go: nahoru, domu]

Skip to content

Commit

Permalink
Add parentNode to FocusScope widget (flutter#114034)
Browse files Browse the repository at this point in the history
  • Loading branch information
gspencergoog committed Oct 25, 2022
1 parent 3ce88d3 commit 8c3806f
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
6 changes: 4 additions & 2 deletions packages/flutter/lib/src/widgets/focus_scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ class FocusScope extends Focus {
const FocusScope({
super.key,
FocusScopeNode? node,
super.parentNode,
required super.child,
super.autofocus,
super.onFocusChange,
Expand All @@ -781,6 +782,7 @@ class FocusScope extends Focus {
Key? key,
required Widget child,
required FocusScopeNode focusScopeNode,
FocusNode? parentNode,
bool autofocus,
ValueChanged<bool>? onFocusChange,
}) = _FocusScopeWithExternalFocusNode;
Expand Down Expand Up @@ -809,13 +811,13 @@ class _FocusScopeWithExternalFocusNode extends FocusScope {
super.key,
required super.child,
required FocusScopeNode focusScopeNode,
super.parentNode,
super.autofocus,
super.onFocusChange,
}) : super(
node: focusScopeNode,
);


@override
bool get _usingExternalFocus => true;
@override
Expand Down Expand Up @@ -846,7 +848,7 @@ class _FocusScopeState extends _FocusState {

@override
Widget build(BuildContext context) {
_focusAttachment!.reparent();
_focusAttachment!.reparent(parent: widget.parentNode);
return Semantics(
explicitChildNodes: true,
child: _FocusMarker(
Expand Down
66 changes: 66 additions & 0 deletions packages/flutter/test/widgets/focus_scope_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,72 @@ void main() {
expect(insertedNode.hasFocus, isFalse);
});

testWidgets('Setting parentNode determines focus scope tree hierarchy.', (WidgetTester tester) async {
final FocusScopeNode topNode = FocusScopeNode(debugLabel: 'Top');
final FocusScopeNode parentNode = FocusScopeNode(debugLabel: 'Parent');
final FocusScopeNode childNode = FocusScopeNode(debugLabel: 'Child');
final FocusScopeNode insertedNode = FocusScopeNode(debugLabel: 'Inserted');

await tester.pumpWidget(
FocusScope.withExternalFocusNode(
focusScopeNode: topNode,
child: Column(
children: <Widget>[
FocusScope.withExternalFocusNode(
focusScopeNode: parentNode,
child: const SizedBox(),
),
FocusScope.withExternalFocusNode(
focusScopeNode: childNode,
parentNode: parentNode,
child: const Focus(
autofocus: true,
child: SizedBox(),
),
)
],
),
),
);
await tester.pump();

expect(childNode.hasFocus, isTrue);
expect(parentNode.hasFocus, isTrue);
expect(topNode.hasFocus, isTrue);

// Check that inserting a Focus in between doesn't reparent the child.
await tester.pumpWidget(
FocusScope.withExternalFocusNode(
focusScopeNode: topNode,
child: Column(
children: <Widget>[
FocusScope.withExternalFocusNode(
focusScopeNode: parentNode,
child: const SizedBox(),
),
FocusScope.withExternalFocusNode(
focusScopeNode: insertedNode,
child: FocusScope.withExternalFocusNode(
focusScopeNode: childNode,
parentNode: parentNode,
child: const Focus(
autofocus: true,
child: SizedBox(),
),
),
)
],
),
),
);
await tester.pump();

expect(childNode.hasFocus, isTrue);
expect(parentNode.hasFocus, isTrue);
expect(topNode.hasFocus, isTrue);
expect(insertedNode.hasFocus, isFalse);
});

// Arguably, this isn't correct behavior, but it is what happens now.
testWidgets("Removing focused widget doesn't move focus to next widget within FocusScope", (WidgetTester tester) async {
final GlobalKey<TestFocusState> keyA = GlobalKey();
Expand Down

0 comments on commit 8c3806f

Please sign in to comment.