Android-Keyboard: Use new show() / hide() methods for keyboard control

Starting with API level 30, Android introduced new
[0]WindowInsetsController.show(int) and [1]hide(int) methods for
controlling the keyboard visibility. This commit updates the code to use
these methods on devices running API 30 and above.

[0]https://developer.android.com/reference/android/view/WindowInsetsController#show(int)
[1]https://developer.android.com/reference/android/view/WindowInsetsController#hide(int)

Task-number: QTBUG-98984
Pick-to: 6.8
Change-Id: Icfcad3430cd269353572f66f72114238045f7756
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 3823d99a688813d2692eb0d4b99939a65bb6ee6a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 75e575e18f0fbfa8571d9044beea3cf3939881ab)
This commit is contained in:
Bartlomiej Moskal 2025-04-08 14:36:56 +02:00 committed by Qt Cherry-pick Bot
parent a72d1c424a
commit 2aae64c041

View File

@ -19,6 +19,8 @@ import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.WindowInsets; import android.view.WindowInsets;
import android.view.WindowInsets.Type; import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimationController;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
@ -127,6 +129,58 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
} }
} }
private void showKeyboard(Activity activity,
final int x, final int y, final int width, final int height,
final int inputHints, final int enterKeyType)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
activity.getWindow().getInsetsController().controlWindowInsetsAnimation(
WindowInsets.Type.ime(), -1, null, null,
new WindowInsetsAnimationControlListener() {
@Override
public void onCancelled(WindowInsetsAnimationController controller) { }
@Override
public void onReady(WindowInsetsAnimationController controller, int types) { }
@Override
public void onFinished(WindowInsetsAnimationController controller) {
QtNativeInputConnection.updateCursorPosition();
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0)
probeForKeyboardHeight(activity, x, y, width, height,
inputHints, enterKeyType);
}
});
activity.getWindow().getInsetsController().show(Type.ime());
} else {
if (m_imm == null)
return;
m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
@Override
@SuppressWarnings("fallthrough")
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case InputMethodManager.RESULT_SHOWN:
QtNativeInputConnection.updateCursorPosition();
//FALLTHROUGH
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0) {
probeForKeyboardHeight(activity,
x, y, width, height, inputHints, enterKeyType);
}
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
}
});
}
}
@Override @Override
public void showSoftwareKeyboard(Activity activity, public void showSoftwareKeyboard(Activity activity,
final int x, final int y, final int width, final int height, final int x, final int y, final int width, final int height,
@ -146,30 +200,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
m_currentEditText.setLayoutParams(new QtLayout.LayoutParams(width, height, x, y)); m_currentEditText.setLayoutParams(new QtLayout.LayoutParams(width, height, x, y));
m_currentEditText.requestFocus(); m_currentEditText.requestFocus();
m_currentEditText.postDelayed(() -> { m_currentEditText.postDelayed(() -> {
if (m_imm == null) showKeyboard(activity, x, y, width, height, inputHints, enterKeyType);
return;
m_imm.showSoftInput(m_currentEditText, 0, new ResultReceiver(new Handler()) {
@Override
@SuppressWarnings("fallthrough")
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case InputMethodManager.RESULT_SHOWN:
QtNativeInputConnection.updateCursorPosition();
//FALLTHROUGH
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0) {
probeForKeyboardHeight(activity,
x, y, width, height, inputHints, enterKeyType);
}
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
}
});
if (m_currentEditText.m_optionsChanged) { if (m_currentEditText.m_optionsChanged) {
m_imm.restartInput(m_currentEditText); m_imm.restartInput(m_currentEditText);
m_currentEditText.m_optionsChanged = false; m_currentEditText.m_optionsChanged = false;
@ -228,22 +259,44 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
if (m_imm == null || m_currentEditText == null) if (m_imm == null || m_currentEditText == null)
return; return;
m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
new ResultReceiver(new Handler()) { Activity activity = QtNative.activity();
@Override if (activity == null) {
protected void onReceiveResult(int resultCode, Bundle resultData) { Log.w(TAG, "hideSoftwareKeyboard: The activity reference is null");
switch (resultCode) { return;
case InputMethodManager.RESULT_SHOWN: }
case InputMethodManager.RESULT_UNCHANGED_SHOWN: activity.getWindow().getInsetsController().controlWindowInsetsAnimation(
setKeyboardVisibility(true, System.nanoTime()); WindowInsets.Type.ime(), -1, null, null,
break; new WindowInsetsAnimationControlListener() {
case InputMethodManager.RESULT_HIDDEN: @Override
case InputMethodManager.RESULT_UNCHANGED_HIDDEN: public void onCancelled(WindowInsetsAnimationController controller) { }
setKeyboardVisibility(false, System.nanoTime()); @Override
break; public void onReady(WindowInsetsAnimationController controller, int types) { }
@Override
public void onFinished(WindowInsetsAnimationController controller) {
setKeyboardVisibility(false, System.nanoTime());
} }
}
}); });
activity.getWindow().getInsetsController().hide(Type.ime());
} else {
m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
new ResultReceiver(new Handler()) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
switch (resultCode) {
case InputMethodManager.RESULT_SHOWN:
case InputMethodManager.RESULT_UNCHANGED_SHOWN:
setKeyboardVisibility(true, System.nanoTime());
break;
case InputMethodManager.RESULT_HIDDEN:
case InputMethodManager.RESULT_UNCHANGED_HIDDEN:
setKeyboardVisibility(false, System.nanoTime());
break;
}
}
});
}
}); });
} }
@ -271,7 +324,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
boolean isKeyboardHidden = true; boolean isKeyboardHidden = true;
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.R) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
Rect r = new Rect(); Rect r = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(r);
DisplayMetrics metrics = new DisplayMetrics(); DisplayMetrics metrics = new DisplayMetrics();