mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
fix jumping input layout on keyboard appearing / disappearing
This commit is contained in:
@@ -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<OnKeyboardHiddenListener> listeners = new HashSet<>(hiddenListeners);
|
||||
for (OnKeyboardHiddenListener listener : listeners) {
|
||||
|
||||
Reference in New Issue
Block a user