Virtual keyboard size adjustment fixes

1. Disable virtual keyboard focus adjustment on Android
The default adjustment setting was causing the view to pan down in order
to adjust the focus on the text content.
We don't need any focus adjustment since we're using a fixed size window
for our application.
Documentation:
https://developer.android.com/reference/android/view/WindowManager.LayoutParams#SOFT_INPUT_ADJUST_NOTHING

2. Fix virtual keyboard height regression
Disabling virtual keyboard focus adjustement caused get_keyboard_height
to always return 0 because it was calculated when the view is resized.
In order to fix it, a PopupWindow is now created on top of the main view
and is set for focus adjustments so the keyboard size can be calculated
based on this popup without affecting the main view.
This commit is contained in:
PouleyKetchoupp 2020-07-24 17:59:57 +02:00
parent 89f57ae122
commit 69db38742f
2 changed files with 43 additions and 7 deletions

View File

@ -69,6 +69,7 @@ import android.os.VibrationEffect;
import android.os.Vibrator; import android.os.Vibrator;
import android.provider.Settings.Secure; import android.provider.Settings.Secure;
import android.view.Display; import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
@ -80,6 +81,7 @@ import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.Button; import android.widget.Button;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.PopupWindow;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
@ -248,6 +250,8 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
public GodotView mView; public GodotView mView;
private boolean godot_initialized = false; private boolean godot_initialized = false;
private PopupWindow mKeyboardWindow;
private SensorManager mSensorManager; private SensorManager mSensorManager;
private Sensor mAccelerometer; private Sensor mAccelerometer;
private Sensor mGravity; private Sensor mGravity;
@ -316,24 +320,36 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
setContentView(layout); setContentView(layout);
// Create a popup window with an invisible layout for the virtual keyboard,
// so the view can be resized to get the vk height without resizing the main godot view.
final FrameLayout keyboardLayout = new FrameLayout(this);
keyboardLayout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
keyboardLayout.setVisibility(View.INVISIBLE);
mKeyboardWindow = new PopupWindow(keyboardLayout, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
mKeyboardWindow.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
mKeyboardWindow.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
mKeyboardWindow.setFocusable(true); // for the text edit to work
mKeyboardWindow.setTouchable(false); // inputs need to go through
// GodotEditText layout // GodotEditText layout
GodotEditText edittext = new GodotEditText(this); GodotEditText edittext = new GodotEditText(this);
edittext.setLayoutParams(new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); edittext.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
// ...add to FrameLayout edittext.setKeyboardView(keyboardLayout);
layout.addView(edittext); // ...add to keyboard layout
keyboardLayout.addView(edittext);
mView = new GodotView(this, xrMode, use_gl3, use_32_bits, use_debug_opengl); mView = new GodotView(this, xrMode, use_gl3, use_32_bits, use_debug_opengl);
layout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); layout.addView(mView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
edittext.setView(mView); edittext.setView(mView);
io.setEdit(edittext); io.setEdit(edittext);
mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { keyboardLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override @Override
public void onGlobalLayout() { public void onGlobalLayout() {
Point fullSize = new Point(); Point fullSize = new Point();
getWindowManager().getDefaultDisplay().getSize(fullSize); getWindowManager().getDefaultDisplay().getSize(fullSize);
Rect gameSize = new Rect(); Rect gameSize = new Rect();
mView.getWindowVisibleDisplayFrame(gameSize); mKeyboardWindow.getContentView().getWindowVisibleDisplayFrame(gameSize);
final int keyboardHeight = fullSize.y - gameSize.bottom; final int keyboardHeight = fullSize.y - gameSize.bottom;
GodotLib.setVirtualKeyboardHeight(keyboardHeight); GodotLib.setVirtualKeyboardHeight(keyboardHeight);
@ -571,6 +587,7 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
super.onCreate(icicle); super.onCreate(icicle);
Window window = getWindow(); Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); window.addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE); mClipboard = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this); pluginRegistry = GodotPluginRegistry.initializePluginRegistry(this);
@ -709,8 +726,21 @@ public abstract class Godot extends FragmentActivity implements SensorEventListe
initializeGodot(); initializeGodot();
} }
@Override
protected void onStart() {
super.onStart();
mView.post(new Runnable() {
@Override
public void run() {
mKeyboardWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, 0, 0);
}
});
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
mKeyboardWindow.dismiss();
for (int i = 0; i < singleton_count; i++) { for (int i = 0; i < singleton_count; i++) {
singletons[i].onMainDestroy(); singletons[i].onMainDestroy();

View File

@ -38,6 +38,7 @@ import android.os.Message;
import android.text.InputFilter; import android.text.InputFilter;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.EditText; import android.widget.EditText;
@ -55,6 +56,7 @@ public class GodotEditText extends EditText {
// Fields // Fields
// =========================================================== // ===========================================================
private GodotView mView; private GodotView mView;
private View mKeyboardView;
private GodotTextInputWrapper mInputWrapper; private GodotTextInputWrapper mInputWrapper;
private EditHandler sHandler = new EditHandler(this); private EditHandler sHandler = new EditHandler(this);
private String mOriginText; private String mOriginText;
@ -117,7 +119,7 @@ public class GodotEditText extends EditText {
edit.mInputWrapper.setOriginText(text); edit.mInputWrapper.setOriginText(text);
edit.addTextChangedListener(edit.mInputWrapper); edit.addTextChangedListener(edit.mInputWrapper);
final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); final InputMethodManager imm = (InputMethodManager)mKeyboardView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(edit, 0); imm.showSoftInput(edit, 0);
} }
} break; } break;
@ -126,7 +128,7 @@ public class GodotEditText extends EditText {
GodotEditText edit = (GodotEditText)msg.obj; GodotEditText edit = (GodotEditText)msg.obj;
edit.removeTextChangedListener(mInputWrapper); edit.removeTextChangedListener(mInputWrapper);
final InputMethodManager imm = (InputMethodManager)mView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); final InputMethodManager imm = (InputMethodManager)mKeyboardView.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(edit.getWindowToken(), 0); imm.hideSoftInputFromWindow(edit.getWindowToken(), 0);
edit.mView.requestFocus(); edit.mView.requestFocus();
} break; } break;
@ -150,6 +152,10 @@ public class GodotEditText extends EditText {
view.requestFocus(); view.requestFocus();
} }
public void setKeyboardView(final View keyboardView) {
this.mKeyboardView = keyboardView;
}
// =========================================================== // ===========================================================
// Methods for/from SuperClass/Interfaces // Methods for/from SuperClass/Interfaces
// =========================================================== // ===========================================================