Skip to content

Commit 9928f4f

Browse files
authored
Android: add support for TextInputType.none (flutter#26585)
1 parent 9e69740 commit 9928f4f

File tree

3 files changed

+78
-6
lines changed

3 files changed

+78
-6
lines changed

shell/platform/android/io/flutter/embedding/engine/systemchannels/TextInputChannel.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,8 @@ public enum TextInputType {
640640
MULTILINE("TextInputType.multiline"),
641641
EMAIL_ADDRESS("TextInputType.emailAddress"),
642642
URL("TextInputType.url"),
643-
VISIBLE_PASSWORD("TextInputType.visiblePassword");
643+
VISIBLE_PASSWORD("TextInputType.visiblePassword"),
644+
NONE("TextInputType.none");
644645

645646
static TextInputType fromValue(@NonNull String encodedName) throws NoSuchFieldException {
646647
for (TextInputType textInputType : TextInputType.values()) {

shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ private static int inputTypeFromTextInputType(
244244
return textType;
245245
} else if (type.type == TextInputChannel.TextInputType.PHONE) {
246246
return InputType.TYPE_CLASS_PHONE;
247+
} else if (type.type == TextInputChannel.TextInputType.NONE) {
248+
return InputType.TYPE_NULL;
247249
}
248250

249251
int textType = InputType.TYPE_CLASS_TEXT;
@@ -365,9 +367,21 @@ public void sendTextInputAppPrivateCommand(String action, Bundle data) {
365367
mImm.sendAppPrivateCommand(mView, action, data);
366368
}
367369

368-
private void showTextInput(View view) {
369-
view.requestFocus();
370-
mImm.showSoftInput(view, 0);
370+
private boolean canShowTextInput() {
371+
if (configuration == null || configuration.inputType == null) {
372+
return true;
373+
}
374+
return configuration.inputType.type != TextInputChannel.TextInputType.NONE;
375+
}
376+
377+
@VisibleForTesting
378+
void showTextInput(View view) {
379+
if (canShowTextInput()) {
380+
view.requestFocus();
381+
mImm.showSoftInput(view, 0);
382+
} else {
383+
hideTextInput(view);
384+
}
371385
}
372386

373387
private void hideTextInput(View view) {
@@ -385,15 +399,19 @@ private void hideTextInput(View view) {
385399
void setTextInputClient(int client, TextInputChannel.Configuration configuration) {
386400
// Call notifyViewExited on the previous field.
387401
notifyViewExited();
388-
inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
402+
this.configuration = configuration;
403+
if (canShowTextInput()) {
404+
inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
405+
} else {
406+
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, client);
407+
}
389408

390409
if (mEditable != null) {
391410
mEditable.removeEditingStateListener(this);
392411
}
393412
mEditable =
394413
new ListenableEditingState(
395414
configuration.autofill != null ? configuration.autofill.editState : null, mView);
396-
this.configuration = configuration;
397415
updateAutofillConfigurationIfNeeded(configuration);
398416

399417
// setTextInputClient will be followed by a call to setTextInputEditingState.

shell/platform/android/test/io/flutter/plugin/editing/TextInputPluginTest.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,59 @@ public void inputConnection_finishComposingTextUpdatesIMM() throws JSONException
604604
assertEquals(0, testImm.getLastCursorAnchorInfo().getComposingText().length());
605605
}
606606

607+
@Test
608+
public void inputConnection_textInputTypeNone() {
609+
View testView = new View(RuntimeEnvironment.application);
610+
DartExecutor dartExecutor = mock(DartExecutor.class);
611+
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
612+
TextInputPlugin textInputPlugin =
613+
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
614+
textInputPlugin.setTextInputClient(
615+
0,
616+
new TextInputChannel.Configuration(
617+
false,
618+
false,
619+
true,
620+
TextInputChannel.TextCapitalization.NONE,
621+
new TextInputChannel.InputType(TextInputChannel.TextInputType.NONE, false, false),
622+
null,
623+
null,
624+
null,
625+
null));
626+
627+
InputConnection connection =
628+
textInputPlugin.createInputConnection(
629+
testView, mock(KeyboardManager.class), new EditorInfo());
630+
assertEquals(connection, null);
631+
}
632+
633+
@Test
634+
public void showTextInput_textInputTypeNone() {
635+
TestImm testImm =
636+
Shadow.extract(
637+
RuntimeEnvironment.application.getSystemService(Context.INPUT_METHOD_SERVICE));
638+
View testView = new View(RuntimeEnvironment.application);
639+
DartExecutor dartExecutor = mock(DartExecutor.class);
640+
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
641+
TextInputPlugin textInputPlugin =
642+
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
643+
textInputPlugin.setTextInputClient(
644+
0,
645+
new TextInputChannel.Configuration(
646+
false,
647+
false,
648+
true,
649+
TextInputChannel.TextCapitalization.NONE,
650+
new TextInputChannel.InputType(TextInputChannel.TextInputType.NONE, false, false),
651+
null,
652+
null,
653+
null,
654+
null));
655+
656+
textInputPlugin.showTextInput(testView);
657+
assertEquals(testImm.isSoftInputVisible(), false);
658+
}
659+
607660
// -------- Start: Autofill Tests -------
608661
@Test
609662
public void autofill_onProvideVirtualViewStructure() {

0 commit comments

Comments
 (0)