From 4a022cd86562016f3cfb05b94f6d616651fe5544 Mon Sep 17 00:00:00 2001 From: cyberta Date: Mon, 15 Jun 2020 12:56:31 +0200 Subject: [PATCH] fix jumping input layout on keyboard appearing / disappearing --- .../components/KeyboardAwareLinearLayout.java | 108 +++++++++++------- 1 file changed, 65 insertions(+), 43 deletions(-) diff --git a/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java b/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java index 64a3159b8..df1739332 100644 --- a/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java +++ b/src/org/thoughtcrime/securesms/components/KeyboardAwareLinearLayout.java @@ -27,7 +27,6 @@ import android.util.AttributeSet; import android.util.Log; import android.view.Surface; import android.view.View; -import android.view.ViewTreeObserver; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.util.ServiceUtil; @@ -41,7 +40,7 @@ import java.util.Set; * LinearLayout that, when a view container, will report back when it thinks a soft keyboard * has been opened and what its height would be. */ -public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements ViewTreeObserver.OnGlobalLayoutListener { +public class KeyboardAwareLinearLayout extends LinearLayoutCompat { private static final String TAG = KeyboardAwareLinearLayout.class.getSimpleName(); private final Rect rect = new Rect(); @@ -50,12 +49,15 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements Vie private final int minKeyboardSize; private final int minCustomKeyboardSize; private final int defaultCustomKeyboardSize; - private final int minCustomKeyboardTopMargin; + private final int minCustomKeyboardTopMarginPortrait; + private final int minCustomKeyboardTopMarginLandscape; private final int statusBarHeight; private int viewInset; private boolean keyboardOpen = false; + private int rotation = -1; + private boolean isFullscreen = false; public KeyboardAwareLinearLayout(Context context) { this(context, null); @@ -68,52 +70,49 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements Vie public KeyboardAwareLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); final int statusBarRes = getResources().getIdentifier("status_bar_height", "dimen", "android"); - minKeyboardSize = getResources().getDimensionPixelSize(R.dimen.min_keyboard_size); - minCustomKeyboardSize = getResources().getDimensionPixelSize(R.dimen.min_custom_keyboard_size); - defaultCustomKeyboardSize = getResources().getDimensionPixelSize(R.dimen.default_custom_keyboard_size); - minCustomKeyboardTopMargin = getResources().getDimensionPixelSize(R.dimen.min_custom_keyboard_top_margin); - statusBarHeight = statusBarRes > 0 ? getResources().getDimensionPixelSize(statusBarRes) : 0; - viewInset = getViewInset(); + minKeyboardSize = getResources().getDimensionPixelSize(R.dimen.min_keyboard_size); + minCustomKeyboardSize = getResources().getDimensionPixelSize(R.dimen.min_custom_keyboard_size); + defaultCustomKeyboardSize = getResources().getDimensionPixelSize(R.dimen.default_custom_keyboard_size); + minCustomKeyboardTopMarginPortrait = getResources().getDimensionPixelSize(R.dimen.min_custom_keyboard_top_margin); + minCustomKeyboardTopMarginLandscape = getResources().getDimensionPixelSize(R.dimen.min_custom_keyboard_top_margin); + statusBarHeight = statusBarRes > 0 ? getResources().getDimensionPixelSize(statusBarRes) : 0; + viewInset = getViewInset(); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ViewTreeObserver observer = this.getViewTreeObserver(); - observer.addOnGlobalLayoutListener(this); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - ViewTreeObserver observer = this.getViewTreeObserver(); - if (Build.VERSION.SDK_INT < 16) { - observer.removeGlobalOnLayoutListener(this); - } else { - observer.removeOnGlobalLayoutListener(this); - } - } - - @Override - public void onGlobalLayout() { + @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + updateRotation(); updateKeyboardState(); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } - public void updateKeyboardState() { - if (isLandscape()) { - if (keyboardOpen) onKeyboardClose(); - return; + private void updateRotation() { + int oldRotation = rotation; + rotation = getDeviceRotation(); + if (oldRotation != rotation) { + Log.i(TAG, "rotation changed"); + onKeyboardClose(); } + } + private void updateKeyboardState() { if (viewInset == 0 && Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) viewInset = getViewInset(); - final int availableHeight = this.getRootView().getHeight() - statusBarHeight - viewInset; + getWindowVisibleDisplayFrame(rect); - final int keyboardHeight = availableHeight - (rect.bottom - rect.top); + final int availableHeight = getAvailableHeight(); + final int keyboardHeight = availableHeight - (rect.bottom - rect.top); if (keyboardHeight > minKeyboardSize) { - if (getKeyboardHeight() != keyboardHeight) setKeyboardPortraitHeight(keyboardHeight); - if (!keyboardOpen) onKeyboardOpen(keyboardHeight); + if (getKeyboardHeight() != keyboardHeight) { + if (isLandscape()) { + setKeyboardLandscapeHeight(keyboardHeight); + } else { + setKeyboardPortraitHeight(keyboardHeight); + } + } + if (!keyboardOpen) { + onKeyboardOpen(keyboardHeight); + } } else if (keyboardOpen) { onKeyboardClose(); } @@ -139,15 +138,27 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements Vie return 0; } + private int getAvailableHeight() { + final int availableHeight = this.getRootView().getHeight() - viewInset - (!isFullscreen ? statusBarHeight : 0); + final int availableWidth = this.getRootView().getWidth() - (!isFullscreen ? statusBarHeight : 0); + + if (isLandscape() && availableHeight > availableWidth) { + //noinspection SuspiciousNameCombination + return availableWidth; + } + + return availableHeight; + } + protected void onKeyboardOpen(int keyboardHeight) { - Log.w(TAG, "onKeyboardOpen(" + keyboardHeight + ")"); + Log.i(TAG, "onKeyboardOpen(" + keyboardHeight + ")"); keyboardOpen = true; notifyShownListeners(); } protected void onKeyboardClose() { - Log.w(TAG, "onKeyboardClose()"); + Log.i(TAG, "onKeyboardClose()"); keyboardOpen = false; notifyHiddenListeners(); } @@ -169,18 +180,25 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements Vie } private int getKeyboardLandscapeHeight() { - return Math.max(getHeight(), getRootView().getHeight()) / 2; + int keyboardHeight = PreferenceManager.getDefaultSharedPreferences(getContext()) + .getInt("keyboard_height_landscape", defaultCustomKeyboardSize); + return Util.clamp(keyboardHeight, minCustomKeyboardSize, getRootView().getHeight() - minCustomKeyboardTopMarginLandscape); } private int getKeyboardPortraitHeight() { int keyboardHeight = PreferenceManager.getDefaultSharedPreferences(getContext()) - .getInt("keyboard_height_portrait", defaultCustomKeyboardSize); - return Util.clamp(keyboardHeight, minCustomKeyboardSize, getRootView().getHeight() - minCustomKeyboardTopMargin); + .getInt("keyboard_height_portrait", defaultCustomKeyboardSize); + return Util.clamp(keyboardHeight, minCustomKeyboardSize, getRootView().getHeight() - minCustomKeyboardTopMarginPortrait); } private void setKeyboardPortraitHeight(int height) { PreferenceManager.getDefaultSharedPreferences(getContext()) - .edit().putInt("keyboard_height_portrait", height).apply(); + .edit().putInt("keyboard_height_portrait", height).apply(); + } + + private void setKeyboardLandscapeHeight(int height) { + PreferenceManager.getDefaultSharedPreferences(getContext()) + .edit().putInt("keyboard_height_landscape", height).apply(); } public void postOnKeyboardClose(final Runnable runnable) { @@ -225,6 +243,10 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat implements Vie shownListeners.remove(listener); } + public void setFullscreen(boolean isFullscreen) { + this.isFullscreen = isFullscreen; + } + private void notifyHiddenListeners() { final Set listeners = new HashSet<>(hiddenListeners); for (OnKeyboardHiddenListener listener : listeners) {