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.8
Change-Id: I40f3ccc4e652f1ae0c6c0ebd154d690d1a9d7ca8
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 33cf82c13d6e3e9fc6d15b725f7ebe15be3d4631)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 3f72e55bca1a368d6432c516b5048b4f6f8fc1b9)
This commit is contained in:
Bartlomiej Moskal 2025-04-09 10:29:00 +02:00 committed by Qt Cherry-pick Bot
parent 2aae64c041
commit b62e1c4794

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;