Skip to content

Commit

Permalink
Replace TextField.canRequestFocus with TextField.focusNode.canRequest…
Browse files Browse the repository at this point in the history
…Focus (#130164)

Simplifying the TextField API.
  • Loading branch information
justinmc authored Aug 2, 2023
1 parent 47b188e commit 9cda309
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 11 deletions.
23 changes: 21 additions & 2 deletions packages/flutter/lib/src/material/dropdown_menu.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
Expand Down Expand Up @@ -309,6 +310,7 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
int? currentHighlight;
double? leadingPadding;
bool _menuHasEnabledItem = false;
late final FocusNode _focusNode;

@override
void initState() {
Expand All @@ -326,6 +328,18 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
TextSelection.collapsed(offset: _textEditingController.text.length);
}
refreshLeadingPadding();
_focusNode = FocusNode(
canRequestFocus: canRequestFocus(),
);
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
final bool widgetCanRequestFocus = canRequestFocus();
if (widgetCanRequestFocus != _focusNode.canRequestFocus) {
_focusNode.canRequestFocus = widgetCanRequestFocus;
}
}

@override
Expand Down Expand Up @@ -353,14 +367,18 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
TextSelection.collapsed(offset: _textEditingController.text.length);
}
}
final bool widgetCanRequestFocus = canRequestFocus();
if (widgetCanRequestFocus != _focusNode.canRequestFocus) {
_focusNode.canRequestFocus = widgetCanRequestFocus;
}
}

bool canRequestFocus() {
if (widget.requestFocusOnTap != null) {
return widget.requestFocusOnTap!;
}

switch (Theme.of(context).platform) {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
case TargetPlatform.android:
case TargetPlatform.fuchsia:
Expand Down Expand Up @@ -592,7 +610,8 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
final Widget textField = TextField(
key: _anchorKey,
mouseCursor: effectiveMouseCursor,
canRequestFocus: canRequestFocus(),
focusNode: _focusNode,
readOnly: !canRequestFocus(),
enableInteractiveSelection: canRequestFocus(),
textAlignVertical: TextAlignVertical.center,
style: effectiveTextStyle,
Expand Down
20 changes: 16 additions & 4 deletions packages/flutter/lib/src/material/text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ class TextField extends StatefulWidget {
this.scribbleEnabled = true,
this.enableIMEPersonalizedLearning = true,
this.contextMenuBuilder = _defaultContextMenuBuilder,
@Deprecated(
'Use `focusNode` instead. '
'This feature was deprecated after v3.12.0-14.0.pre.',
)
this.canRequestFocus = true,
this.spellCheckConfiguration,
this.magnifierConfiguration,
Expand Down Expand Up @@ -776,6 +780,10 @@ class TextField extends StatefulWidget {
/// Defaults to true. If false, the text field will not request focus
/// when tapped, or when its context menu is displayed. If false it will not
/// be possible to move the focus to the text field with tab key.
@Deprecated(
'Use `focusNode` instead. '
'This feature was deprecated after v3.12.0-14.0.pre.',
)
final bool canRequestFocus;

/// {@macro flutter.widgets.undoHistory.controller}
Expand Down Expand Up @@ -1026,15 +1034,19 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
if (widget.controller == null) {
_createLocalController();
}
_effectiveFocusNode.canRequestFocus = widget.canRequestFocus && _isEnabled;
_effectiveFocusNode.canRequestFocus = widget.focusNode == null
? widget.canRequestFocus && _isEnabled
: widget.focusNode!.canRequestFocus && _isEnabled;
_effectiveFocusNode.addListener(_handleFocusChanged);
}

bool get _canRequestFocus {
final NavigationMode mode = MediaQuery.maybeNavigationModeOf(context) ?? NavigationMode.traditional;
switch (mode) {
case NavigationMode.traditional:
return widget.canRequestFocus && _isEnabled;
return widget.focusNode == null
? widget.canRequestFocus && _isEnabled
: widget.focusNode!.canRequestFocus && _isEnabled;
case NavigationMode.directional:
return true;
}
Expand Down Expand Up @@ -1086,8 +1098,8 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
void _createLocalController([TextEditingValue? value]) {
assert(_controller == null);
_controller = value == null
? RestorableTextEditingController()
: RestorableTextEditingController.fromValue(value);
? RestorableTextEditingController()
: RestorableTextEditingController.fromValue(value);
if (!restorePending) {
_registerController();
}
Expand Down
7 changes: 3 additions & 4 deletions packages/flutter/test/material/dropdown_menu_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1232,7 +1232,7 @@ void main() {

final Finder textFieldFinder = find.byType(TextField);
final TextField result = tester.widget<TextField>(textFieldFinder);
expect(result.canRequestFocus, false);
expect(result.focusNode!.canRequestFocus, false);
}, variant: TargetPlatformVariant.mobile());

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

final Finder textFieldFinder1 = find.byType(TextField);
final TextField textField1 = tester.widget<TextField>(textFieldFinder1);
expect(textField1.canRequestFocus, false);
expect(textField1.focusNode!.canRequestFocus, false);
// Open the dropdown menu.
await tester.tap(textFieldFinder1);
await tester.pump();
Expand Down Expand Up @@ -1329,7 +1329,7 @@ void main() {

final Finder textFieldFinder = find.byType(TextField);
final TextField textField = tester.widget<TextField>(textFieldFinder);
expect(textField.canRequestFocus, false);
expect(textField.focusNode!.canRequestFocus, false);

final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
await gesture.moveTo(tester.getCenter(textFieldFinder));
Expand Down Expand Up @@ -1526,7 +1526,6 @@ void main() {
// Item 5 should show up.
expect(find.text('Item 5').hitTestable(), findsOneWidget);
});

}

enum TestMenu {
Expand Down
5 changes: 4 additions & 1 deletion packages/flutter/test/material/text_field_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15568,6 +15568,7 @@ void main() {
expect(focusNode.hasFocus, isTrue);

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

testWidgets('Right clicking cannot request focus if canRequestFocus is false', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode();
final FocusNode focusNode = FocusNode(
canRequestFocus: false,
);
final UniqueKey key = UniqueKey();
await tester.pumpWidget(
MaterialApp(
Expand Down

0 comments on commit 9cda309

Please sign in to comment.