[TextInput] send setEditingState
before show
to the text input plugin when switching input clients (#92945)
This commit is contained in:
parent
a1115b8b3f
commit
23c20d702b
@ -2207,16 +2207,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
_textInputConnection = _needsAutofill && currentAutofillScope != null
|
_textInputConnection = _needsAutofill && currentAutofillScope != null
|
||||||
? currentAutofillScope!.attach(this, _effectiveAutofillClient.textInputConfiguration)
|
? currentAutofillScope!.attach(this, _effectiveAutofillClient.textInputConfiguration)
|
||||||
: TextInput.attach(this, _effectiveAutofillClient.textInputConfiguration);
|
: TextInput.attach(this, _effectiveAutofillClient.textInputConfiguration);
|
||||||
_textInputConnection!.show();
|
|
||||||
_updateSizeAndTransform();
|
_updateSizeAndTransform();
|
||||||
_updateComposingRectIfNeeded();
|
_updateComposingRectIfNeeded();
|
||||||
_updateCaretRectIfNeeded();
|
_updateCaretRectIfNeeded();
|
||||||
if (_needsAutofill) {
|
|
||||||
// Request autofill AFTER the size and the transform have been sent to
|
|
||||||
// the platform text input plugin.
|
|
||||||
_textInputConnection!.requestAutofill();
|
|
||||||
}
|
|
||||||
|
|
||||||
final TextStyle style = widget.style;
|
final TextStyle style = widget.style;
|
||||||
_textInputConnection!
|
_textInputConnection!
|
||||||
..setStyle(
|
..setStyle(
|
||||||
@ -2226,8 +2219,14 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
|
|||||||
textDirection: _textDirection,
|
textDirection: _textDirection,
|
||||||
textAlign: widget.textAlign,
|
textAlign: widget.textAlign,
|
||||||
)
|
)
|
||||||
..setEditingState(localValue);
|
..setEditingState(localValue)
|
||||||
_lastKnownRemoteTextEditingValue = localValue;
|
..show();
|
||||||
|
if (_needsAutofill) {
|
||||||
|
// Request autofill AFTER the size and the transform have been sent to
|
||||||
|
// the platform text input plugin.
|
||||||
|
_textInputConnection!.requestAutofill();
|
||||||
|
}
|
||||||
|
_lastKnownRemoteTextEditingValue = localValue;
|
||||||
} else {
|
} else {
|
||||||
_textInputConnection!.show();
|
_textInputConnection!.show();
|
||||||
}
|
}
|
||||||
|
@ -6619,14 +6619,18 @@ void main() {
|
|||||||
));
|
));
|
||||||
|
|
||||||
await tester.showKeyboard(find.byType(EditableText));
|
await tester.showKeyboard(find.byType(EditableText));
|
||||||
// TextInput.show should be before TextInput.setEditingState
|
// TextInput.show should be after TextInput.setEditingState.
|
||||||
|
// On Android setEditingState triggers an IME restart which may prevent
|
||||||
|
// the keyboard from showing if the show keyboard request comes before the
|
||||||
|
// restart.
|
||||||
|
// See: https://github.com/flutter/flutter/issues/68571.
|
||||||
final List<String> logOrder = <String>[
|
final List<String> logOrder = <String>[
|
||||||
'TextInput.setClient',
|
'TextInput.setClient',
|
||||||
'TextInput.show',
|
|
||||||
'TextInput.setEditableSizeAndTransform',
|
'TextInput.setEditableSizeAndTransform',
|
||||||
'TextInput.setMarkedTextRect',
|
'TextInput.setMarkedTextRect',
|
||||||
'TextInput.setStyle',
|
'TextInput.setStyle',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
|
'TextInput.show',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
'TextInput.show',
|
'TextInput.show',
|
||||||
'TextInput.setCaretRect',
|
'TextInput.setCaretRect',
|
||||||
@ -6637,6 +6641,67 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets(
|
||||||
|
'keyboard is requested after setEditingState after switching to a new text field',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
// Regression test for https://github.com/flutter/flutter/issues/68571.
|
||||||
|
final EditableText editableText1 = EditableText(
|
||||||
|
showSelectionHandles: true,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: TextEditingController(),
|
||||||
|
focusNode: FocusNode(),
|
||||||
|
cursorColor: Colors.red,
|
||||||
|
backgroundCursorColor: Colors.blue,
|
||||||
|
style: Typography.material2018().black.subtitle1!.copyWith(fontFamily: 'Roboto'),
|
||||||
|
keyboardType: TextInputType.text,
|
||||||
|
);
|
||||||
|
|
||||||
|
final EditableText editableText2 = EditableText(
|
||||||
|
showSelectionHandles: true,
|
||||||
|
maxLines: 2,
|
||||||
|
controller: TextEditingController(),
|
||||||
|
focusNode: FocusNode(),
|
||||||
|
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],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
await tester.tap(find.byWidget(editableText1));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
tester.testTextInput.log.clear();
|
||||||
|
await tester.tap(find.byWidget(editableText2));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// Send TextInput.show after TextInput.setEditingState. Otherwise
|
||||||
|
// some Android keyboards ignore the "show keyboard" request, as the
|
||||||
|
// Android text input plugin restarts the input method when setEditingState
|
||||||
|
// is sent by the framework.
|
||||||
|
final List<String> logOrder = <String>[
|
||||||
|
'TextInput.clearClient',
|
||||||
|
'TextInput.setClient',
|
||||||
|
'TextInput.setEditableSizeAndTransform',
|
||||||
|
'TextInput.setMarkedTextRect',
|
||||||
|
'TextInput.setStyle',
|
||||||
|
'TextInput.setEditingState',
|
||||||
|
'TextInput.show',
|
||||||
|
'TextInput.setCaretRect',
|
||||||
|
];
|
||||||
|
expect(
|
||||||
|
tester.testTextInput.log.map((MethodCall m) => m.method),
|
||||||
|
logOrder,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
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!';
|
||||||
@ -6666,11 +6731,11 @@ void main() {
|
|||||||
|
|
||||||
final List<String> logOrder = <String>[
|
final List<String> logOrder = <String>[
|
||||||
'TextInput.setClient',
|
'TextInput.setClient',
|
||||||
'TextInput.show',
|
|
||||||
'TextInput.setEditableSizeAndTransform',
|
'TextInput.setEditableSizeAndTransform',
|
||||||
'TextInput.setMarkedTextRect',
|
'TextInput.setMarkedTextRect',
|
||||||
'TextInput.setStyle',
|
'TextInput.setStyle',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
|
'TextInput.show',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
'TextInput.show',
|
'TextInput.show',
|
||||||
'TextInput.setCaretRect',
|
'TextInput.setCaretRect',
|
||||||
@ -6716,11 +6781,11 @@ void main() {
|
|||||||
|
|
||||||
final List<String> logOrder = <String>[
|
final List<String> logOrder = <String>[
|
||||||
'TextInput.setClient',
|
'TextInput.setClient',
|
||||||
'TextInput.show',
|
|
||||||
'TextInput.setEditableSizeAndTransform',
|
'TextInput.setEditableSizeAndTransform',
|
||||||
'TextInput.setMarkedTextRect',
|
'TextInput.setMarkedTextRect',
|
||||||
'TextInput.setStyle',
|
'TextInput.setStyle',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
|
'TextInput.show',
|
||||||
'TextInput.setEditingState',
|
'TextInput.setEditingState',
|
||||||
'TextInput.show',
|
'TextInput.show',
|
||||||
'TextInput.setCaretRect',
|
'TextInput.setCaretRect',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user