Skip to content

Commit 9cda309

Browse files
authored
Replace TextField.canRequestFocus with TextField.focusNode.canRequestFocus (flutter#130164)
Simplifying the TextField API.
1 parent 47b188e commit 9cda309

File tree

4 files changed

+44
-11
lines changed

4 files changed

+44
-11
lines changed

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:math' as math;
66

7+
import 'package:flutter/foundation.dart';
78
import 'package:flutter/rendering.dart';
89
import 'package:flutter/services.dart';
910
import 'package:flutter/widgets.dart';
@@ -309,6 +310,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
309310
int? currentHighlight;
310311
double? leadingPadding;
311312
bool _menuHasEnabledItem = false;
313+
late final FocusNode _focusNode;
312314

313315
@override
314316
void initState() {
@@ -326,6 +328,18 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
326328
TextSelection.collapsed(offset: _textEditingController.text.length);
327329
}
328330
refreshLeadingPadding();
331+
_focusNode = FocusNode(
332+
canRequestFocus: canRequestFocus(),
333+
);
334+
}
335+
336+
@override
337+
void didChangeDependencies() {
338+
super.didChangeDependencies();
339+
final bool widgetCanRequestFocus = canRequestFocus();
340+
if (widgetCanRequestFocus != _focusNode.canRequestFocus) {
341+
_focusNode.canRequestFocus = widgetCanRequestFocus;
342+
}
329343
}
330344

331345
@override
@@ -353,14 +367,18 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
353367
TextSelection.collapsed(offset: _textEditingController.text.length);
354368
}
355369
}
370+
final bool widgetCanRequestFocus = canRequestFocus();
371+
if (widgetCanRequestFocus != _focusNode.canRequestFocus) {
372+
_focusNode.canRequestFocus = widgetCanRequestFocus;
373+
}
356374
}
357375

358376
bool canRequestFocus() {
359377
if (widget.requestFocusOnTap != null) {
360378
return widget.requestFocusOnTap!;
361379
}
362380

363-
switch (Theme.of(context).platform) {
381+
switch (defaultTargetPlatform) {
364382
case TargetPlatform.iOS:
365383
case TargetPlatform.android:
366384
case TargetPlatform.fuchsia:
@@ -592,7 +610,8 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
592610
final Widget textField = TextField(
593611
key: _anchorKey,
594612
mouseCursor: effectiveMouseCursor,
595-
canRequestFocus: canRequestFocus(),
613+
focusNode: _focusNode,
614+
readOnly: !canRequestFocus(),
596615
enableInteractiveSelection: canRequestFocus(),
597616
textAlignVertical: TextAlignVertical.center,
598617
style: effectiveTextStyle,

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

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ class TextField extends StatefulWidget {
314314
this.scribbleEnabled = true,
315315
this.enableIMEPersonalizedLearning = true,
316316
this.contextMenuBuilder = _defaultContextMenuBuilder,
317+
@Deprecated(
318+
'Use `focusNode` instead. '
319+
'This feature was deprecated after v3.12.0-14.0.pre.',
320+
)
317321
this.canRequestFocus = true,
318322
this.spellCheckConfiguration,
319323
this.magnifierConfiguration,
@@ -776,6 +780,10 @@ class TextField extends StatefulWidget {
776780
/// Defaults to true. If false, the text field will not request focus
777781
/// when tapped, or when its context menu is displayed. If false it will not
778782
/// be possible to move the focus to the text field with tab key.
783+
@Deprecated(
784+
'Use `focusNode` instead. '
785+
'This feature was deprecated after v3.12.0-14.0.pre.',
786+
)
779787
final bool canRequestFocus;
780788

781789
/// {@macro flutter.widgets.undoHistory.controller}
@@ -1026,15 +1034,19 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
10261034
if (widget.controller == null) {
10271035
_createLocalController();
10281036
}
1029-
_effectiveFocusNode.canRequestFocus = widget.canRequestFocus && _isEnabled;
1037+
_effectiveFocusNode.canRequestFocus = widget.focusNode == null
1038+
? widget.canRequestFocus && _isEnabled
1039+
: widget.focusNode!.canRequestFocus && _isEnabled;
10301040
_effectiveFocusNode.addListener(_handleFocusChanged);
10311041
}
10321042

10331043
bool get _canRequestFocus {
10341044
final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
10351045
switch (mode) {
10361046
case NavigationMode.traditional:
1037-
return widget.canRequestFocus && _isEnabled;
1047+
return widget.focusNode == null
1048+
? widget.canRequestFocus && _isEnabled
1049+
: widget.focusNode!.canRequestFocus && _isEnabled;
10381050
case NavigationMode.directional:
10391051
return true;
10401052
}
@@ -1086,8 +1098,8 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
10861098
void _createLocalController([TextEditingValue? value]) {
10871099
assert(_controller == null);
10881100
_controller = value == null
1089-
? RestorableTextEditingController()
1090-
: RestorableTextEditingController.fromValue(value);
1101+
? RestorableTextEditingController()
1102+
: RestorableTextEditingController.fromValue(value);
10911103
if (!restorePending) {
10921104
_registerController();
10931105
}

packages/flutter/test/material/dropdown_menu_test.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,7 @@ void main() {
12321232

12331233
final Finder textFieldFinder = find.byType(TextField);
12341234
final TextField result = tester.widget<TextField>(textFieldFinder);
1235-
expect(result.canRequestFocus, false);
1235+
expect(result.focusNode!.canRequestFocus, false);
12361236
}, variant: TargetPlatformVariant.mobile());
12371237

12381238
testWidgets('The text input field should be focused on desktop platforms '
@@ -1300,7 +1300,7 @@ void main() {
13001300

13011301
final Finder textFieldFinder1 = find.byType(TextField);
13021302
final TextField textField1 = tester.widget<TextField>(textFieldFinder1);
1303-
expect(textField1.canRequestFocus, false);
1303+
expect(textField1.focusNode!.canRequestFocus, false);
13041304
// Open the dropdown menu.
13051305
await tester.tap(textFieldFinder1);
13061306
await tester.pump();
@@ -1329,7 +1329,7 @@ void main() {
13291329

13301330
final Finder textFieldFinder = find.byType(TextField);
13311331
final TextField textField = tester.widget<TextField>(textFieldFinder);
1332-
expect(textField.canRequestFocus, false);
1332+
expect(textField.focusNode!.canRequestFocus, false);
13331333

13341334
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
13351335
await gesture.moveTo(tester.getCenter(textFieldFinder));
@@ -1526,7 +1526,6 @@ void main() {
15261526
// Item 5 should show up.
15271527
expect(find.text('Item 5').hitTestable(), findsOneWidget);
15281528
});
1529-
15301529
}
15311530

15321531
enum TestMenu {

packages/flutter/test/material/text_field_test.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15568,6 +15568,7 @@ void main() {
1556815568
expect(focusNode.hasFocus, isTrue);
1556915569

1557015570
// Set canRequestFocus to false: the text field cannot be focused when it is tapped/long pressed.
15571+
focusNode.canRequestFocus = false;
1557115572
await tester.pumpWidget(
1557215573
boilerplate(
1557315574
child: TextField(
@@ -15749,7 +15750,9 @@ void main() {
1574915750
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }));
1575015751

1575115752
testWidgets('Right clicking cannot request focus if canRequestFocus is false', (WidgetTester tester) async {
15752-
final FocusNode focusNode = FocusNode();
15753+
final FocusNode focusNode = FocusNode(
15754+
canRequestFocus: false,
15755+
);
1575315756
final UniqueKey key = UniqueKey();
1575415757
await tester.pumpWidget(
1575515758
MaterialApp(

0 commit comments

Comments
 (0)