mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add parentNode to FocusScope widget (#114034)
This commit is contained in:
parent
3ce88d3813
commit
8c3806f817
@ -760,6 +760,7 @@ class FocusScope extends Focus {
|
|||||||
const FocusScope({
|
const FocusScope({
|
||||||
super.key,
|
super.key,
|
||||||
FocusScopeNode? node,
|
FocusScopeNode? node,
|
||||||
|
super.parentNode,
|
||||||
required super.child,
|
required super.child,
|
||||||
super.autofocus,
|
super.autofocus,
|
||||||
super.onFocusChange,
|
super.onFocusChange,
|
||||||
@ -781,6 +782,7 @@ class FocusScope extends Focus {
|
|||||||
Key? key,
|
Key? key,
|
||||||
required Widget child,
|
required Widget child,
|
||||||
required FocusScopeNode focusScopeNode,
|
required FocusScopeNode focusScopeNode,
|
||||||
|
FocusNode? parentNode,
|
||||||
bool autofocus,
|
bool autofocus,
|
||||||
ValueChanged<bool>? onFocusChange,
|
ValueChanged<bool>? onFocusChange,
|
||||||
}) = _FocusScopeWithExternalFocusNode;
|
}) = _FocusScopeWithExternalFocusNode;
|
||||||
@ -809,13 +811,13 @@ class _FocusScopeWithExternalFocusNode extends FocusScope {
|
|||||||
super.key,
|
super.key,
|
||||||
required super.child,
|
required super.child,
|
||||||
required FocusScopeNode focusScopeNode,
|
required FocusScopeNode focusScopeNode,
|
||||||
|
super.parentNode,
|
||||||
super.autofocus,
|
super.autofocus,
|
||||||
super.onFocusChange,
|
super.onFocusChange,
|
||||||
}) : super(
|
}) : super(
|
||||||
node: focusScopeNode,
|
node: focusScopeNode,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get _usingExternalFocus => true;
|
bool get _usingExternalFocus => true;
|
||||||
@override
|
@override
|
||||||
@ -846,7 +848,7 @@ class _FocusScopeState extends _FocusState {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
_focusAttachment!.reparent();
|
_focusAttachment!.reparent(parent: widget.parentNode);
|
||||||
return Semantics(
|
return Semantics(
|
||||||
explicitChildNodes: true,
|
explicitChildNodes: true,
|
||||||
child: _FocusMarker(
|
child: _FocusMarker(
|
||||||
|
@ -532,6 +532,72 @@ void main() {
|
|||||||
expect(insertedNode.hasFocus, isFalse);
|
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.
|
// 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 {
|
testWidgets("Removing focused widget doesn't move focus to next widget within FocusScope", (WidgetTester tester) async {
|
||||||
final GlobalKey<TestFocusState> keyA = GlobalKey();
|
final GlobalKey<TestFocusState> keyA = GlobalKey();
|
||||||
|
Loading…
Reference in New Issue
Block a user