From aa3a3de66139ed55de25c4706defb532deea4a33 Mon Sep 17 00:00:00 2001 From: sspanak Date: Sun, 23 Feb 2025 19:34:55 +0200 Subject: [PATCH] fixed the insets randomly zero on Android 15 for the third time (aka I really hate edge-to-edge) --- .../github/sspanak/tt9/hacks/DeviceInfo.java | 17 +++++ .../sspanak/tt9/ui/main/BaseMainLayout.java | 62 ++++++++++--------- .../tt9/ui/main/ResizableMainView.java | 9 +-- app/src/main/res/values/dimens.xml | 2 + 4 files changed, 56 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/io/github/sspanak/tt9/hacks/DeviceInfo.java b/app/src/main/java/io/github/sspanak/tt9/hacks/DeviceInfo.java index 702d6d5a..157cc2b5 100644 --- a/app/src/main/java/io/github/sspanak/tt9/hacks/DeviceInfo.java +++ b/app/src/main/java/io/github/sspanak/tt9/hacks/DeviceInfo.java @@ -10,6 +10,8 @@ import android.view.KeyEvent; import androidx.annotation.NonNull; +import io.github.sspanak.tt9.R; + public class DeviceInfo { private static Resources resources; @@ -24,6 +26,21 @@ public class DeviceInfo { return getResources(context).getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE; } + public static int getNavigationBarHeight(Context context, boolean isLandscape) { + Resources resources = getResources(context); + + // navBarMode = 0: 3-button, 1 = 2-button, 2 = gesture + int resourceId = resources.getIdentifier("config_navBarInteractionMode", "integer", "android"); + int navBarMode = resourceId > 0 ? resources.getInteger(resourceId) : 0; + + int navBarHeight = resources.getDimensionPixelSize(R.dimen.android_navigation_bar_height); + if (isLandscape) { + return navBarMode == 0 ? 0 : navBarHeight; + } else { + return navBarHeight; + } + } + public static int getScreenWidth(Context context) { return getResources(context).getDisplayMetrics().widthPixels; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java index 46082a39..abb30d34 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/BaseMainLayout.java @@ -16,12 +16,14 @@ import androidx.core.view.WindowInsetsCompat; import java.util.ArrayList; import io.github.sspanak.tt9.R; +import io.github.sspanak.tt9.hacks.DeviceInfo; import io.github.sspanak.tt9.ime.TraditionalT9; import io.github.sspanak.tt9.ui.main.keys.SoftKey; import io.github.sspanak.tt9.util.ThemedContextBuilder; abstract class BaseMainLayout { - private static ViewGroup.MarginLayoutParams edgeToEdgeMargins = null; + protected int e2ePaddingBottomLandscape = -1; + protected int e2ePaddingBottomPortrait = -1; protected final TraditionalT9 tt9; private final int xml; @@ -76,26 +78,36 @@ abstract class BaseMainLayout { @RequiresApi(api = Build.VERSION_CODES.VANILLA_ICE_CREAM) protected WindowInsets preventEdgeToEdge(@NonNull View v, @NonNull WindowInsets windowInsets) { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); - ViewGroup.MarginLayoutParams marginParams = setMargins(v, insets.right, insets.bottom, insets.left); - if (marginParams != null) { - edgeToEdgeMargins = marginParams; - return WindowInsets.CONSUMED; + v.setPadding(insets.left, 0, insets.right, insets.bottom); + + // cache the padding for use when the insets are not available + if (e2ePaddingBottomLandscape < 0 || e2ePaddingBottomPortrait < 0) { + boolean isLandscape = DeviceInfo.isLandscapeOrientation(view.getContext()); + if (isLandscape) { + e2ePaddingBottomLandscape = insets.bottom; + } else { + e2ePaddingBottomPortrait = insets.bottom; + } } - return windowInsets; + return WindowInsets.CONSUMED; } /** - * Similar to the above method, but reuses the last known margins. Useful for when the Main View + * Similar to the above method, but reuses the last known padding. Useful for when the Main View * is re-created and it is not yet possible to get the new window insets. */ public void preventEdgeToEdge() { - if (view == null || edgeToEdgeMargins == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { + if (tt9 == null || view == null || Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM) { return; } - setMargins(view, edgeToEdgeMargins.rightMargin, edgeToEdgeMargins.bottomMargin, edgeToEdgeMargins.leftMargin); + boolean isLandscape = DeviceInfo.isLandscapeOrientation(view.getContext()); + + int bottomPadding = isLandscape ? e2ePaddingBottomLandscape : e2ePaddingBottomPortrait; + bottomPadding = bottomPadding < 0 ? DeviceInfo.getNavigationBarHeight(view.getContext(), isLandscape) : bottomPadding; + view.setPadding(view.getPaddingLeft(), 0, view.getPaddingRight(), bottomPadding); } @@ -129,40 +141,30 @@ abstract class BaseMainLayout { } - private ViewGroup.MarginLayoutParams setMargins(View v, int right, int bottom, int left) { - if (v == null) { - return null; - } - - ViewGroup.MarginLayoutParams layout = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); - if (layout != null) { - layout.rightMargin = right; - layout.bottomMargin = bottom; - layout.leftMargin = left; - v.setLayoutParams(layout); - } - - return layout; - } - - int getHeight(boolean forceRecalculate) { return 0; } - boolean setHeight(int height) { - if (view == null) { + int getKeyboardHeight() { + View keyboard = view != null ? view.findViewById(R.id.keyboard_container) : null; + return keyboard != null ? keyboard.getMeasuredHeight() : 0; + } + + + boolean setKeyboardHeight(int height) { + View keyboard = view != null ? view.findViewById(R.id.keyboard_container) : null; + if (keyboard == null) { return false; } - ViewGroup.LayoutParams params = view.getLayoutParams(); + ViewGroup.LayoutParams params = keyboard.getLayoutParams(); if (params == null) { return false; } params.height = height; - view.setLayoutParams(params); + keyboard.setLayoutParams(params); return true; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/ResizableMainView.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/ResizableMainView.java index 6f52fc56..392f10d8 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/ResizableMainView.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/ResizableMainView.java @@ -63,8 +63,8 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha @Override public void onViewDetachedFromWindow(@NonNull View v) {} @Override public void onViewAttachedToWindow(@NonNull View v) { - setHeight(height, heightSmall, heightNumpad); main.preventEdgeToEdge(); + setHeight(height, heightSmall, heightNumpad); } @@ -180,11 +180,12 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha private boolean changeHeight(int delta, int minHeight, int maxHeight) { - if (main == null || main.getView() == null) { + int keyboardHeight = main.getKeyboardHeight(); + if (keyboardHeight == 0) { return false; } - return setHeight(main.getView().getMeasuredHeight() + delta, minHeight, maxHeight); + return setHeight(keyboardHeight + delta, minHeight, maxHeight); } @@ -194,7 +195,7 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha } height = Math.min(height, maxHeight); - if (main.setHeight(height)) { + if (main.setKeyboardHeight(height)) { this.height = height; return true; } diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 93ee422e..14f75604 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -5,6 +5,8 @@ to ignore the Android text size scale. We can't allow scaling because it breaks the layout. --> + 48dp + 21dp