Android: Do not hide keyboard when opening

It takes some time to display the keyboard. For this reason, in case the
keyboard was not displayed yet - we could wrongly assume that the
keyboard is hiding. To avoid this situation, there is a new check.
In case the keyboard has just been opened and it is not displayed yet,
the execution of HideKeyboardRunnable is postponed to give time for the
keyboard to be displayed.

Fixes: QTBUG-130000
Change-Id: Iee1310c777ebbb807990bf3cec39e6d07481dfad
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 4de9b94042dd173c6db31a4641a1513a9b319a79)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Rami Potinkara 2024-10-17 20:50:10 +03:00 committed by Qt Cherry-pick Bot
parent 0a32e20b11
commit 7e4b10677f
2 changed files with 44 additions and 1 deletions

View File

@ -66,12 +66,15 @@ class QtInputConnection extends BaseInputConnection
private static final int ID_COPY_URL = android.R.id.copyUrl; private static final int ID_COPY_URL = android.R.id.copyUrl;
private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod; private static final int ID_SWITCH_INPUT_METHOD = android.R.id.switchInputMethod;
private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary; private static final int ID_ADD_TO_DICTIONARY = android.R.id.addToDictionary;
private static final int KEYBOARD_CHECK_DELAY_MS = 100;
private static final String QtTAG = "QtInputConnection"; private static final String QtTAG = "QtInputConnection";
private final QtInputConnectionListener m_qtInputConnectionListener; private final QtInputConnectionListener m_qtInputConnectionListener;
class HideKeyboardRunnable implements Runnable { class HideKeyboardRunnable implements Runnable {
private int m_numberOfAttempts = 10;
@Override @Override
public void run() { public void run() {
// Check that the keyboard is really no longer there. // Check that the keyboard is really no longer there.
@ -79,6 +82,14 @@ class QtInputConnection extends BaseInputConnection
Log.w(QtTAG, "HideKeyboardRunnable: QtInputConnectionListener is null"); Log.w(QtTAG, "HideKeyboardRunnable: QtInputConnectionListener is null");
return; return;
} }
if (m_qtInputConnectionListener.keyboardTransitionInProgress()
&& m_numberOfAttempts > 0) {
--m_numberOfAttempts;
m_view.postDelayed(this, KEYBOARD_CHECK_DELAY_MS);
return;
}
if (m_qtInputConnectionListener.isKeyboardHidden()) if (m_qtInputConnectionListener.isKeyboardHidden())
m_qtInputConnectionListener.onHideKeyboardRunnableDone(false, System.nanoTime()); m_qtInputConnectionListener.onHideKeyboardRunnableDone(false, System.nanoTime());
} }
@ -89,6 +100,7 @@ class QtInputConnection extends BaseInputConnection
void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp); void onHideKeyboardRunnableDone(boolean visibility, long hideTimeStamp);
void onSendKeyEventDefaultCase(); void onSendKeyEventDefaultCase();
void onEditTextChanged(QtEditText editText); void onEditTextChanged(QtEditText editText);
boolean keyboardTransitionInProgress();
boolean isKeyboardHidden(); boolean isKeyboardHidden();
} }
@ -98,7 +110,7 @@ class QtInputConnection extends BaseInputConnection
private void setClosing(boolean closing) private void setClosing(boolean closing)
{ {
if (closing) if (closing)
m_view.postDelayed(new HideKeyboardRunnable(), 100); m_view.postDelayed(new HideKeyboardRunnable(), KEYBOARD_CHECK_DELAY_MS);
else if (m_qtInputConnectionListener != null) else if (m_qtInputConnectionListener != null)
m_qtInputConnectionListener.onSetClosing(false); m_qtInputConnectionListener.onSetClosing(false);
} }

View File

@ -20,6 +20,7 @@ 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.WindowManager; import android.view.WindowManager;
import android.view.ViewTreeObserver;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener; import org.qtproject.qt.android.QtInputConnection.QtInputConnectionListener;
@ -52,6 +53,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
// That is why we assume that the keyboard should be higher than 0.15 of the screen. // That is why we assume that the keyboard should be higher than 0.15 of the screen.
private static final float KEYBOARD_TO_SCREEN_RATIO = 0.15f; private static final float KEYBOARD_TO_SCREEN_RATIO = 0.15f;
private boolean m_keyboardTransitionInProgress = false;
private boolean m_keyboardIsVisible = false; private boolean m_keyboardIsVisible = false;
private boolean m_isKeyboardHidingAnimationOngoing = false; private boolean m_isKeyboardHidingAnimationOngoing = false;
private long m_showHideTimeStamp = System.nanoTime(); private long m_showHideTimeStamp = System.nanoTime();
@ -91,6 +93,28 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
Log.w(TAG, "getSystemService() returned a null InputMethodManager instance"); Log.w(TAG, "getSystemService() returned a null InputMethodManager instance");
} }
private final ViewTreeObserver.OnGlobalLayoutListener keyboardListener =
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (!isKeyboardHidden())
setKeyboardTransitionInProgress(false);
}
};
private void setKeyboardTransitionInProgress(boolean state)
{
if (m_keyboardTransitionInProgress == state || m_currentEditText == null)
return;
m_keyboardTransitionInProgress= state;
ViewTreeObserver observer = m_currentEditText.getViewTreeObserver();
if (state)
observer.addOnGlobalLayoutListener(keyboardListener);
else
observer.removeOnGlobalLayoutListener(keyboardListener);
}
// QtInputInterface implementation begin // QtInputInterface implementation begin
@Override @Override
public void updateSelection(final int selStart, final int selEnd, public void updateSelection(final int selStart, final int selEnd,
@ -234,6 +258,11 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
// QtInputInterface implementation end // QtInputInterface implementation end
// QtInputConnectionListener methods // QtInputConnectionListener methods
@Override
public boolean keyboardTransitionInProgress() {
return m_keyboardTransitionInProgress;
}
@Override @Override
public boolean isKeyboardHidden() { public boolean isKeyboardHidden() {
Activity activity = QtNative.activity(); Activity activity = QtNative.activity();
@ -313,6 +342,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
return; return;
m_keyboardIsVisible = visibility; m_keyboardIsVisible = visibility;
keyboardVisibilityUpdated(m_keyboardIsVisible); keyboardVisibilityUpdated(m_keyboardIsVisible);
setKeyboardTransitionInProgress(visibility);
if (!visibility) { if (!visibility) {
// Hiding the keyboard clears the immersive mode, so we need to set it again. // Hiding the keyboard clears the immersive mode, so we need to set it again.
@ -324,6 +354,7 @@ class QtInputDelegate implements QtInputConnection.QtInputConnectionListener, Qt
void setFocusedView(QtEditText currentEditText) void setFocusedView(QtEditText currentEditText)
{ {
setKeyboardTransitionInProgress(false);
m_currentEditText = currentEditText; m_currentEditText = currentEditText;
} }