Android: Reliably showing an IME for text input dialog (#13521)

This commit is inspired by this blog post: https://developer.squareup.com/blog/showing-the-android-keyboard-reliably/
This commit is contained in:
Muhammad Rifqi Priyo Susanto 2023-07-01 14:00:30 +07:00 committed by GitHub
parent 0ade097e99
commit ff498fc206
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 15 deletions

@ -2,6 +2,8 @@
Minetest Minetest
Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua> Copyright (C) 2014-2020 MoNTE48, Maksim Gamarnik <MoNTE48@mail.ua>
Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com> Copyright (C) 2014-2020 ubulem, Bektur Mambetov <berkut87@gmail.com>
Copyright (C) 2023 srifqi, Muhammad Rifqi Priyo Susanto
<muhammadrifqipriyosusanto@gmail.com>
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
@ -29,17 +31,52 @@ import androidx.appcompat.widget.AppCompatEditText;
import java.util.Objects; import java.util.Objects;
public class CustomEditText extends AppCompatEditText { public class CustomEditText extends AppCompatEditText {
private int editType = 2; // single line text input as default
private boolean wantsToShowKeyboard = false;
public CustomEditText(Context context) { public CustomEditText(Context context) {
super(context); super(context);
} }
public CustomEditText(Context context, int _editType) {
super(context);
editType = _editType;
}
@Override @Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) { public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) { // For multi-line, do not close the dialog after pressing back button
if (editType != 1 && keyCode == KeyEvent.KEYCODE_BACK) {
InputMethodManager mgr = (InputMethodManager) InputMethodManager mgr = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE); getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
Objects.requireNonNull(mgr).hideSoftInputFromWindow(this.getWindowToken(), 0); Objects.requireNonNull(mgr).hideSoftInputFromWindow(this.getWindowToken(), 0);
} }
return false; return false;
} }
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
tryShowKeyboard();
}
public void requestFocusTryShow() {
requestFocus();
wantsToShowKeyboard = true;
tryShowKeyboard();
}
private void tryShowKeyboard() {
if (hasWindowFocus() && wantsToShowKeyboard) {
if (isFocused()) {
CustomEditText that = this;
post(() -> {
final InputMethodManager imm = (InputMethodManager)
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(that, 0);
});
}
wantsToShowKeyboard = false;
}
}
} }

@ -31,7 +31,6 @@ import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import androidx.annotation.Keep; import androidx.annotation.Keep;
@ -96,21 +95,11 @@ public class GameActivity extends NativeActivity {
container.setOrientation(LinearLayout.VERTICAL); container.setOrientation(LinearLayout.VERTICAL);
builder.setView(container); builder.setView(container);
AlertDialog alertDialog = builder.create(); AlertDialog alertDialog = builder.create();
EditText editText; CustomEditText editText = new CustomEditText(this, editType);
// For multi-line, do not close the dialog after pressing back button
if (editType == 1) {
editText = new EditText(this);
} else {
editText = new CustomEditText(this);
}
container.addView(editText); container.addView(editText);
editText.setMaxLines(8); editText.setMaxLines(8);
editText.requestFocus();
editText.setHint(hint); editText.setHint(hint);
editText.setText(current); editText.setText(current);
final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
Objects.requireNonNull(imm).toggleSoftInput(InputMethodManager.SHOW_FORCED,
InputMethodManager.HIDE_IMPLICIT_ONLY);
if (editType == 1) if (editType == 1)
editText.setInputType(InputType.TYPE_CLASS_TEXT | editText.setInputType(InputType.TYPE_CLASS_TEXT |
InputType.TYPE_TEXT_FLAG_MULTI_LINE); InputType.TYPE_TEXT_FLAG_MULTI_LINE);
@ -119,7 +108,8 @@ public class GameActivity extends NativeActivity {
InputType.TYPE_TEXT_VARIATION_PASSWORD); InputType.TYPE_TEXT_VARIATION_PASSWORD);
else else
editText.setInputType(InputType.TYPE_CLASS_TEXT); editText.setInputType(InputType.TYPE_CLASS_TEXT);
editText.setSelection(editText.getText().length()); editText.setSelection(Objects.requireNonNull(editText.getText()).length());
final InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
editText.setOnKeyListener((view, keyCode, event) -> { editText.setOnKeyListener((view, keyCode, event) -> {
// For multi-line, do not submit the text after pressing Enter key // For multi-line, do not submit the text after pressing Enter key
if (keyCode == KeyEvent.KEYCODE_ENTER && editType != 1) { if (keyCode == KeyEvent.KEYCODE_ENTER && editType != 1) {
@ -143,12 +133,13 @@ public class GameActivity extends NativeActivity {
alertDialog.dismiss(); alertDialog.dismiss();
})); }));
} }
alertDialog.show();
alertDialog.setOnCancelListener(dialog -> { alertDialog.setOnCancelListener(dialog -> {
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
messageReturnValue = current; messageReturnValue = current;
messageReturnCode = -1; messageReturnCode = -1;
}); });
alertDialog.show();
editText.requestFocusTryShow();
} }
public int getDialogState() { public int getDialogState() {