Android-Keyboard: Improve keyboard visibility tracking

Starting with API level 30, keyboard visibility can be easly checked
using [0]WindowInsets.isVisible(int). This eliminates the need for
relying on callbacks to detect when the keyboard opens or closes.

This commit updates the logic to track keyboard visibility by
observing changes via OnApplyWindowInsetsListener and checking for
visibility changes using the new API.  From now on, for API 30 and
above, the internal keyboard visibility property should no longer be
updated manually.

[0] https://developer.android.com/reference/android/view/WindowInsets#isVisible(int)

Task-number: QTBUG-98984
Pick-to: 6.10 6.9 6.8
Change-Id: I40f3ccc4e652f1ae0c6c0ebd154d690d1a9d7ca8
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Bartlomiej Moskal 2025-04-09 10:29:00 +02:00
parent 3823d99a68
commit 33cf82c13d

View File

@ -22,6 +22,7 @@ import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimationController;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowManager;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager;
@ -90,6 +91,18 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
m_imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
if (m_imm == null)
Log.w(TAG, "getSystemService() returned a null InputMethodManager instance");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
View rootView = activity.getWindow().getDecorView();
rootView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
@Override
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
if (m_keyboardIsVisible != insets.isVisible(WindowInsets.Type.ime()))
setKeyboardVisibility_internal(!m_keyboardIsVisible, System.nanoTime());
return insets;
}
});
}
}
private final ViewTreeObserver.OnGlobalLayoutListener keyboardListener =
@ -146,7 +159,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
@Override
public void onFinished(WindowInsetsAnimationController controller) {
QtNativeInputConnection.updateCursorPosition();
setKeyboardVisibility(true, System.nanoTime());
if (m_softInputMode == 0)
probeForKeyboardHeight(activity, x, y, width, height,
inputHints, enterKeyType);
@ -265,19 +277,6 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
Log.w(TAG, "hideSoftwareKeyboard: The activity reference is null");
return;
}
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) {
setKeyboardVisibility(false, System.nanoTime());
}
});
activity.getWindow().getInsetsController().hide(Type.ime());
} else {
m_imm.hideSoftInputFromWindow(m_currentEditText.getWindowToken(), 0,
@ -384,6 +383,14 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
}
void setKeyboardVisibility(boolean visibility, long timeStamp)
{
// Since API 30 keyboard visibility changes are tracked by OnApplyWindowInsetsListener.
// There are no manual changes anymore
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
setKeyboardVisibility_internal(visibility, timeStamp);
}
private void setKeyboardVisibility_internal(boolean visibility, long timeStamp)
{
if (m_showHideTimeStamp > timeStamp)
return;