[Android] Reset IME state in TextInputPlugin.clearTextInputClient (flutter/engine#49829)
## Description
This PR calls Android API `InputMethodManager.restartInput` to reset IMEs internal states. Otherwise some IMEs (Gboard for instance) keep reacting based on the previous input configuration until a new configuration is set.
- On Android native, `restartInput` is called in several places, for instance in f219798774/android/widget/TextView.java (L2458).
- On Compose, https://github.com/flutter/flutter/issues/70546#issuecomment-1088345561 pointed out where it is called.
- On Flutter, it is called at some point but mainly when another `TextField` is focused (it is mainly called in `setTextInputEditingState`).
## Related Issue
Fixes https://github.com/flutter/flutter/issues/70546.
## Tests
Adds 1 test.
This commit is contained in:
@@ -569,6 +569,10 @@ public class TextInputPlugin implements ListenableEditingState.EditingStateWatch
|
||||
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
|
||||
unlockPlatformViewInputConnection();
|
||||
lastClientRect = null;
|
||||
|
||||
// Call restartInput to reset IME internal states. Otherwise some IMEs (Gboard for instance)
|
||||
// keep reacting based on the previous input configuration until a new configuration is set.
|
||||
mImm.restartInput(mView);
|
||||
}
|
||||
|
||||
private static class InputTarget {
|
||||
|
||||
@@ -1128,6 +1128,41 @@ public class TextInputPluginTest {
|
||||
assertEquals(1, testImm.getRestartCount(testView));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clearTextInputClient_alwaysRestartsImm() {
|
||||
// Initialize a general TextInputPlugin.
|
||||
InputMethodSubtype inputMethodSubtype = mock(InputMethodSubtype.class);
|
||||
TestImm testImm = Shadow.extract(ctx.getSystemService(Context.INPUT_METHOD_SERVICE));
|
||||
testImm.setCurrentInputMethodSubtype(inputMethodSubtype);
|
||||
View testView = new View(ctx);
|
||||
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
|
||||
TextInputPlugin textInputPlugin =
|
||||
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
|
||||
textInputPlugin.setTextInputClient(
|
||||
0,
|
||||
new TextInputChannel.Configuration(
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
TextInputChannel.TextCapitalization.NONE,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null));
|
||||
// There's a pending restart since we initialized the text input client. Flush that now.
|
||||
textInputPlugin.setTextInputEditingState(
|
||||
testView, new TextInputChannel.TextEditState("", 0, 0, -1, -1));
|
||||
assertEquals(1, testImm.getRestartCount(testView));
|
||||
|
||||
// A restart is always forced when calling clearTextInputClient().
|
||||
textInputPlugin.clearTextInputClient();
|
||||
assertEquals(2, testImm.getRestartCount(testView));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void destroy_clearTextInputMethodHandler() {
|
||||
View testView = new View(ctx);
|
||||
|
||||
Reference in New Issue
Block a user