Unverified Commit 266fb87c authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Update the Focus widget to update the node's onKey handler when the widget updates (#74909)

This updates the onKey handler of the FocusNode that the Focus widget manages when the widget is updated and the handler has changed. Also added a setter for onKey to the FocusNode.
parent 9d5a540c
...@@ -432,7 +432,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier { ...@@ -432,7 +432,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
/// arguments must not be null. /// arguments must not be null.
FocusNode({ FocusNode({
String? debugLabel, String? debugLabel,
FocusOnKeyCallback? onKey, this.onKey,
bool skipTraversal = false, bool skipTraversal = false,
bool canRequestFocus = true, bool canRequestFocus = true,
bool descendantsAreFocusable = true, bool descendantsAreFocusable = true,
...@@ -441,8 +441,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier { ...@@ -441,8 +441,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
assert(descendantsAreFocusable != null), assert(descendantsAreFocusable != null),
_skipTraversal = skipTraversal, _skipTraversal = skipTraversal,
_canRequestFocus = canRequestFocus, _canRequestFocus = canRequestFocus,
_descendantsAreFocusable = descendantsAreFocusable, _descendantsAreFocusable = descendantsAreFocusable {
_onKey = onKey {
// Set it via the setter so that it does nothing on release builds. // Set it via the setter so that it does nothing on release builds.
this.debugLabel = debugLabel; this.debugLabel = debugLabel;
} }
...@@ -573,8 +572,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier { ...@@ -573,8 +572,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
/// [hasFocus] returns true). /// [hasFocus] returns true).
/// ///
/// {@macro flutter.widgets.FocusNode.keyEvents} /// {@macro flutter.widgets.FocusNode.keyEvents}
FocusOnKeyCallback? get onKey => _onKey; FocusOnKeyCallback? onKey;
FocusOnKeyCallback? _onKey;
FocusManager? _manager; FocusManager? _manager;
List<FocusNode>? _ancestors; List<FocusNode>? _ancestors;
...@@ -1028,7 +1026,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier { ...@@ -1028,7 +1026,7 @@ class FocusNode with DiagnosticableTreeMixin, ChangeNotifier {
@mustCallSuper @mustCallSuper
FocusAttachment attach(BuildContext? context, {FocusOnKeyCallback? onKey}) { FocusAttachment attach(BuildContext? context, {FocusOnKeyCallback? onKey}) {
_context = context; _context = context;
_onKey = onKey ?? _onKey; this.onKey = onKey ?? this.onKey;
_attachment = FocusAttachment._(this); _attachment = FocusAttachment._(this);
return _attachment!; return _attachment!;
} }
......
...@@ -643,6 +643,9 @@ class _FocusState extends State<Focus> { ...@@ -643,6 +643,9 @@ class _FocusState extends State<Focus> {
}()); }());
if (oldWidget.focusNode == widget.focusNode) { if (oldWidget.focusNode == widget.focusNode) {
if (widget.onKey != focusNode.onKey) {
focusNode.onKey = widget.onKey;
}
if (widget.skipTraversal != null) { if (widget.skipTraversal != null) {
focusNode.skipTraversal = widget.skipTraversal!; focusNode.skipTraversal = widget.skipTraversal!;
} }
......
...@@ -4,9 +4,10 @@ ...@@ -4,9 +4,10 @@
import 'dart:ui'; import 'dart:ui';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/semantics.dart'; import 'package:flutter/semantics.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'semantics_tester.dart'; import 'semantics_tester.dart';
...@@ -1593,6 +1594,37 @@ void main() { ...@@ -1593,6 +1594,37 @@ void main() {
final TestSemantics expectedSemantics = TestSemantics.root(); final TestSemantics expectedSemantics = TestSemantics.root();
expect(semantics, hasSemantics(expectedSemantics)); expect(semantics, hasSemantics(expectedSemantics));
}); });
testWidgets('Focus updates the onKey handler when the widget updates', (WidgetTester tester) async {
final GlobalKey key1 = GlobalKey(debugLabel: '1');
final FocusNode focusNode = FocusNode();
bool? keyEventHandled;
await tester.pumpWidget(
Focus(
onKey: (_, __) => true, // This one does nothing.
focusNode: focusNode,
child: Container(key: key1),
),
);
Focus.of(key1.currentContext!).requestFocus();
await tester.pump();
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
expect(keyEventHandled, isNull);
await tester.pumpWidget(
Focus(
onKey: (FocusNode node, RawKeyEvent event) { // The updated handler handles the key.
keyEventHandled = true;
return true;
},
focusNode: focusNode,
child: Container(key: key1),
),
);
await tester.sendKeyEvent(LogicalKeyboardKey.enter);
expect(keyEventHandled, isTrue);
});
}); });
group('ExcludeFocus', () { group('ExcludeFocus', () {
testWidgets("Descendants of ExcludeFocus aren't focusable.", (WidgetTester tester) async { testWidgets("Descendants of ExcludeFocus aren't focusable.", (WidgetTester tester) async {
......
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