EditableText does not request focus on autofill (#97846)
This commit is contained in:
parent
3f9c0e74f2
commit
6656356bbf
@ -2391,8 +2391,27 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
widget.controller.selection = selection;
|
widget.controller.selection = selection;
|
||||||
|
|
||||||
// This will show the keyboard for all selection changes on the
|
// This will show the keyboard for all selection changes on the
|
||||||
// EditableWidget, not just changes triggered by user gestures.
|
// EditableText except for those triggered by a keyboard input.
|
||||||
requestKeyboard();
|
// Typically EditableText shouldn't take user keyboard input if
|
||||||
|
// it's not focused already. If the EditableText is being
|
||||||
|
// autofilled it shouldn't request focus.
|
||||||
|
switch (cause) {
|
||||||
|
case null:
|
||||||
|
case SelectionChangedCause.doubleTap:
|
||||||
|
case SelectionChangedCause.drag:
|
||||||
|
case SelectionChangedCause.forcePress:
|
||||||
|
case SelectionChangedCause.longPress:
|
||||||
|
case SelectionChangedCause.scribble:
|
||||||
|
case SelectionChangedCause.tap:
|
||||||
|
case SelectionChangedCause.toolbar:
|
||||||
|
requestKeyboard();
|
||||||
|
break;
|
||||||
|
case SelectionChangedCause.keyboard:
|
||||||
|
if (_hasFocus) {
|
||||||
|
requestKeyboard();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (widget.selectionControls == null) {
|
if (widget.selectionControls == null) {
|
||||||
_selectionOverlay?.dispose();
|
_selectionOverlay?.dispose();
|
||||||
_selectionOverlay = null;
|
_selectionOverlay = null;
|
||||||
|
@ -3013,8 +3013,6 @@ void main() {
|
|||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorBackwardByWord,
|
SemanticsAction.moveCursorBackwardByWord,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3049,8 +3047,6 @@ void main() {
|
|||||||
actions: <SemanticsAction>[
|
actions: <SemanticsAction>[
|
||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3122,8 +3118,6 @@ void main() {
|
|||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorBackwardByWord,
|
SemanticsAction.moveCursorBackwardByWord,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3156,8 +3150,6 @@ void main() {
|
|||||||
actions: <SemanticsAction>[
|
actions: <SemanticsAction>[
|
||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3240,8 +3232,6 @@ void main() {
|
|||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorBackwardByWord,
|
SemanticsAction.moveCursorBackwardByWord,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3276,8 +3266,6 @@ void main() {
|
|||||||
actions: <SemanticsAction>[
|
actions: <SemanticsAction>[
|
||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3360,8 +3348,6 @@ void main() {
|
|||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorBackwardByWord,
|
SemanticsAction.moveCursorBackwardByWord,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -3394,8 +3380,6 @@ void main() {
|
|||||||
actions: <SemanticsAction>[
|
actions: <SemanticsAction>[
|
||||||
SemanticsAction.moveCursorForwardByCharacter,
|
SemanticsAction.moveCursorForwardByCharacter,
|
||||||
SemanticsAction.moveCursorForwardByWord,
|
SemanticsAction.moveCursorForwardByWord,
|
||||||
SemanticsAction.setSelection,
|
|
||||||
SemanticsAction.setText,
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -8137,6 +8121,57 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'Autofill does not request focus',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/91354 .
|
||||||
|
final FocusNode focusNode1 = FocusNode();
|
||||||
|
final EditableText editableText1 = EditableText(
|
||||||
|
showSelectionHandles: true,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: TextEditingController(),
|
||||||
|
focusNode: focusNode1,
|
||||||
|
cursorColor: Colors.red,
|
||||||
|
backgroundCursorColor: Colors.blue,
|
||||||
|
style: Typography.material2018().black.subtitle1!.copyWith(fontFamily: 'Roboto'),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
final FocusNode focusNode2 = FocusNode();
|
||||||
|
final EditableText editableText2 = EditableText(
|
||||||
|
showSelectionHandles: true,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: TextEditingController(),
|
||||||
|
focusNode: focusNode2,
|
||||||
|
cursorColor: Colors.red,
|
||||||
|
backgroundCursorColor: Colors.blue,
|
||||||
|
style: Typography.material2018().black.subtitle1!.copyWith(fontFamily: 'Roboto'),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
home: Center(
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[editableText1, editableText2],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
// editableText1 has the focus.
|
||||||
|
await tester.tap(find.byWidget(editableText1));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
final EditableTextState state2 = tester.state<EditableTextState>(find.byWidget(editableText2));
|
||||||
|
// Update editableText2 when it's not focused. It should not request focus.
|
||||||
|
state2.updateEditingValue(
|
||||||
|
const TextEditingValue(text: 'password', selection: TextSelection.collapsed(offset: 8)),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(focusNode1.hasFocus, isTrue);
|
||||||
|
expect(focusNode2.hasFocus, isFalse);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('setEditingState is not called when text changes', (WidgetTester tester) async {
|
testWidgets('setEditingState is not called when text changes', (WidgetTester tester) async {
|
||||||
// We shouldn't get a message here because this change is owned by the platform side.
|
// We shouldn't get a message here because this change is owned by the platform side.
|
||||||
const String testText = 'flutter is the best!';
|
const String testText = 'flutter is the best!';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user