From d23efc4e607c67d94dc0ebe0002cb17c8ec7e7f1 Mon Sep 17 00:00:00 2001 From: sspanak Date: Fri, 31 Jan 2025 20:13:33 +0200 Subject: [PATCH] fixed all alignment and size issues, especially on Android 15; got rid of the ConstraintLayout --- app/build.gradle | 1 - .../screens/appearance/ItemNumpadWidth.java | 10 +- .../tt9/preferences/settings/SettingsUI.java | 28 ++++-- .../sspanak/tt9/ui/main/BaseMainLayout.java | 57 ++++++++++-- .../sspanak/tt9/ui/main/MainLayoutNumpad.java | 93 +++++++++++++------ .../sspanak/tt9/ui/main/MainLayoutTray.java | 2 +- .../tt9/ui/main/ResizableMainView.java | 23 ++--- app/src/main/res/layout/main_numpad.xml | 47 ++++------ app/src/main/res/values/styles.xml | 23 ++--- 9 files changed, 184 insertions(+), 100 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 07c8f6dd..03137b75 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -165,5 +165,4 @@ android { dependencies { implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.preference:preference:1.2.1' - implementation 'androidx.constraintlayout:constraintlayout:2.2.0' } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/appearance/ItemNumpadWidth.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/appearance/ItemNumpadWidth.java index 0b9b70c6..5c1b3c45 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/appearance/ItemNumpadWidth.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/appearance/ItemNumpadWidth.java @@ -20,13 +20,9 @@ public class ItemNumpadWidth extends ItemDropDown { @Override public ItemDropDown populate() { LinkedHashMap options = new LinkedHashMap<>(); - options.put(70, "70 %"); - options.put(75, "75 %"); - options.put(80, "80 %"); - options.put(85, "85 %"); - options.put(90, "90 %"); - options.put(95, "95 %"); - options.put(100, "100 %"); + for (int i = SettingsStore.MIN_WIDTH_PERCENT; i <= 100; i += 5) { + options.put(i, i + " %"); + } super.populateIntegers(options); float currentValue = settings.getNumpadWidthPercent(); diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsUI.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsUI.java index 3fc8187d..4c39d440 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsUI.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsUI.java @@ -22,6 +22,9 @@ public class SettingsUI extends SettingsTyping { private final int DEFAULT_LAYOUT; private final boolean DEFAULT_STATUS_ICON; + public final static int MIN_WIDTH_PERCENT = 50; + private int DEFAULT_WIDTH_LANDSCAPE = 0; + SettingsUI(Context context) { super(context); @@ -79,16 +82,29 @@ public class SettingsUI extends SettingsTyping { return getStringifiedInt("pref_numpad_key_height", getNumpadKeyDefaultHeight()); } - public int getNumpadMaxWidth() { - return Math.min(context.getResources().getDimensionPixelSize(R.dimen.numpad_max_width), DeviceInfo.getScreenWidth(context)); - } + public int getNumpadDefaultWidthPercent() { + if (!DeviceInfo.isLandscapeOrientation(context)) { + return 100; + } - public int getNumpadWidth() { - return getNumpadWidthPercent() * getNumpadMaxWidth() / 100; + if (DEFAULT_WIDTH_LANDSCAPE > 0) { + return DEFAULT_WIDTH_LANDSCAPE; + } + + int screenWidth = DeviceInfo.getScreenWidth(context.getApplicationContext()); + if (screenWidth < 1) { + return 100; + } + + int stylesMaxWidth = Math.round(context.getResources().getDimension(R.dimen.numpad_max_width)); + float width = screenWidth < stylesMaxWidth ? 100 : 100f * stylesMaxWidth / screenWidth; + width = width < MIN_WIDTH_PERCENT ? MIN_WIDTH_PERCENT : width; + + return DEFAULT_WIDTH_LANDSCAPE = Math.round(width / 5) * 5; } public int getNumpadWidthPercent() { - return getStringifiedInt("pref_numpad_width", 100); + return getStringifiedInt("pref_numpad_width", getNumpadDefaultWidthPercent()); } public int getSettingsFontSize() { 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 738c4f3a..b60900e6 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 @@ -1,5 +1,6 @@ package io.github.sspanak.tt9.ui.main; +import android.graphics.Insets; import android.os.Build; import android.view.ContextThemeWrapper; import android.view.View; @@ -7,6 +8,8 @@ import android.view.ViewGroup; import android.view.WindowInsets; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.core.view.WindowInsetsCompat; import java.util.ArrayList; @@ -46,24 +49,45 @@ abstract class BaseMainLayout { .setTheme(R.style.TTheme) .build(); view = View.inflate(themedContext, xml, null); + view.setOnApplyWindowInsetsListener(this::onApplyInsets); } return view; } + protected WindowInsets onApplyInsets(@NonNull View v, @NonNull WindowInsets windowInsets) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM) { + return preventEdgeToEdge(v, windowInsets); + } else { + return windowInsets; + } + } + + /** - * Calculate the bottom padding for the edge-to-edge mode in Android 15+. Without padding, + * Apply the padding to prevent edge-to-edge on Android 15+. Without padding, * the bottom of the View will be cut off by the system navigation bar. */ - protected int getBottomInsetSize() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.VANILLA_ICE_CREAM || tt9 == null) { - return 0; + @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 layout = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); + if (layout != null) { + layout.rightMargin = insets.right; + layout.bottomMargin = insets.bottom; + layout.leftMargin = insets.left; + v.setLayoutParams(layout); } - final int DEFAULT_SIZE = 96; - WindowInsets insets = tt9.getWindow().findViewById(android.R.id.content).getRootWindowInsets(); - return insets != null ? insets.getStableInsetBottom() : DEFAULT_SIZE; + return WindowInsets.CONSUMED; + } + + + void requestPreventEdgeToEdge() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.VANILLA_ICE_CREAM && view != null) { + view.requestApplyInsets(); + } } @@ -95,6 +119,25 @@ abstract class BaseMainLayout { } + boolean setHeight(int height) { + if (view == null) { + return false; + } + + ViewGroup.LayoutParams params = view.getLayoutParams(); + if (params == null) { + return false; + } + + params.height = height; + view.setLayoutParams(params); + return true; + } + + + void setWidth(int widthPercent) {} + + abstract void showCommandPalette(); abstract void hideCommandPalette(); abstract boolean isCommandPaletteShown(); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java index ceea92de..ef25d880 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutNumpad.java @@ -1,7 +1,7 @@ package io.github.sspanak.tt9.ui.main; import android.content.res.Resources; -import android.os.Build; +import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; @@ -28,17 +28,6 @@ class MainLayoutNumpad extends BaseMainLayout { super(tt9, R.layout.main_numpad); } - private void alignView() { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || view == null) { - return; - } - - LinearLayout container = view.findViewById(R.id.numpad_container); - if (container != null) { - container.setGravity(tt9.getSettings().getNumpadAlignment()); - } - } - @Override void showCommandPalette() {} @Override void hideCommandPalette() {} @@ -163,42 +152,92 @@ class MainLayoutNumpad extends BaseMainLayout { int getHeight(boolean forceRecalculate) { if (height <= 0 || forceRecalculate) { Resources resources = tt9.getResources(); - height = getKeyHeightCompat() * 4 + height = + Math.round(resources.getDimension(R.dimen.numpad_status_bar_spacing_top)) + resources.getDimensionPixelSize(R.dimen.numpad_status_bar_spacing_bottom) + resources.getDimensionPixelSize(R.dimen.numpad_suggestion_height) - + Math.round(resources.getDimension(R.dimen.numpad_keys_spacing_bottom)) - + getBottomInsetSize(); + + getKeyHeightCompat() * 4 + + Math.round(resources.getDimension(R.dimen.numpad_keys_spacing_bottom)); } return height; } - private void setWidth(int width) { - if (view == null || width <= 0) { + /** + * Adjusts the width of the keyboard to the given percentage of the screen width. + */ + private void setKeyboardWidth(int widthPercent) { + View keyboard = view != null ? view.findViewById(R.id.numpad_container) : null; + if (keyboard == null) { return; } - View widthConstraintWrapper = view.findViewById(R.id.numpad_width_constraint_wrapper); - if (widthConstraintWrapper == null) { - return; - } - - ViewGroup.LayoutParams layout = widthConstraintWrapper.getLayoutParams(); + LinearLayout.LayoutParams layout = (LinearLayout.LayoutParams) keyboard.getLayoutParams(); if (layout != null) { - layout.width = width; - widthConstraintWrapper.setLayoutParams(layout); + layout.weight = widthPercent; + keyboard.setLayoutParams(layout); } } + /** + * Adjust the padding on both sides of the keyboard to make it centered, or aligned to the + * left or right. + */ + private void setBumperWidth(int widthPercent, int gravity) { + View leftBumper = view.findViewById(R.id.numpad_bumper_left); + View rightBumper = view.findViewById(R.id.numpad_bumper_right); + if (leftBumper == null || rightBumper == null) { + return; + } + + int leftPadding = 0; + int rightPadding = 0; + + switch (gravity) { + case Gravity.CENTER_HORIZONTAL: + leftPadding = rightPadding = (100 - widthPercent) / 2; + break; + + case Gravity.START: + rightPadding = 100 - widthPercent; + break; + + case Gravity.END: + leftPadding = 100 - widthPercent; + break; + } + + LinearLayout.LayoutParams layout = (LinearLayout.LayoutParams) leftBumper.getLayoutParams(); + if (layout != null) { + layout.weight = leftPadding; + leftBumper.setLayoutParams(layout); + } + + layout = (LinearLayout.LayoutParams) rightBumper.getLayoutParams(); + if (layout != null) { + layout.weight = rightPadding; + rightBumper.setLayoutParams(layout); + } + } + + + void setWidth(int widthPercent, int gravity) { + if (view == null || widthPercent <= 0 || widthPercent > 100) { + return; + } + + setBumperWidth(widthPercent, gravity); + setKeyboardWidth(widthPercent); + } + + @Override void render() { getView(); - alignView(); setKeyHeight(getKeyHeightCompat()); - setWidth(tt9.getSettings().getNumpadWidth()); + setWidth(tt9.getSettings().getNumpadWidthPercent(), tt9.getSettings().getNumpadAlignment()); enableClickHandlers(); for (SoftKey key : getKeys()) { key.render(); diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutTray.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutTray.java index c2f9dfc8..61506983 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutTray.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/MainLayoutTray.java @@ -21,7 +21,7 @@ class MainLayoutTray extends BaseMainLayout { int getHeight(boolean forceRecalculate) { if (height <= 0 || forceRecalculate) { Resources resources = tt9.getResources(); - height = resources.getDimensionPixelSize(R.dimen.status_bar_height) + getBottomInsetSize(); + height = resources.getDimensionPixelSize(R.dimen.status_bar_height); if (isCommandPaletteShown() || isTextEditingPaletteShown()) { height += resources.getDimensionPixelSize(R.dimen.main_small_command_palette_height); 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 75a6fb7d..6898c0fa 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 @@ -3,7 +3,6 @@ package io.github.sspanak.tt9.ui.main; import android.os.Build; import android.view.Gravity; import android.view.View; -import android.view.ViewGroup; import androidx.annotation.NonNull; @@ -58,7 +57,10 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha } } - @Override public void onViewAttachedToWindow(@NonNull View v) { setHeight(height, heightSmall, heightNumpad); } + @Override public void onViewAttachedToWindow(@NonNull View v) { + setHeight(height, heightSmall, heightNumpad); + main.setWidth(tt9.getSettings().getNumpadWidthPercent()); + } @Override public void onViewDetachedFromWindow(@NonNull View v) {} @@ -136,11 +138,13 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha settings.setMainViewLayout(SettingsStore.LAYOUT_SMALL); height = heightSmall; tt9.onCreateInputView(); + main.requestPreventEdgeToEdge(); vibration.vibrate(); } else if (settings.isMainLayoutSmall()) { settings.setMainViewLayout(SettingsStore.LAYOUT_NUMPAD); height = (int) Math.max(Math.max(heightNumpad * 0.6, heightSmall * 1.1), height + delta); tt9.onCreateInputView(); + main.requestPreventEdgeToEdge(); vibration.vibrate(); } else { changeHeight(delta, heightSmall, heightNumpad); @@ -159,11 +163,13 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha settings.setMainViewLayout(SettingsStore.LAYOUT_TRAY); height = heightTray; tt9.onCreateInputView(); + main.requestPreventEdgeToEdge(); vibration.vibrate(); } else if (!changeHeight(delta, heightSmall, heightNumpad)) { settings.setMainViewLayout(SettingsStore.LAYOUT_SMALL); height = heightSmall; tt9.onCreateInputView(); + main.requestPreventEdgeToEdge(); vibration.vibrate(); } } @@ -184,17 +190,12 @@ public class ResizableMainView extends MainView implements View.OnAttachStateCha } height = Math.min(height, maxHeight); - - ViewGroup.LayoutParams params = main.getView().getLayoutParams(); - if (params == null) { - return false; + if (main.setHeight(height)) { + this.height = height; + return true; } - params.height = height; - main.getView().setLayoutParams(params); - this.height = height; - - return true; + return false; } private void fitMain() { diff --git a/app/src/main/res/layout/main_numpad.xml b/app/src/main/res/layout/main_numpad.xml index e23d7b0a..8ae71b73 100644 --- a/app/src/main/res/layout/main_numpad.xml +++ b/app/src/main/res/layout/main_numpad.xml @@ -1,34 +1,27 @@ - + - + + + + + - - - - - - - - - - - + android:id="@+id/main_soft_keys" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal"> + + + + - + + + + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index b035bbbd..61a4ba26 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -139,29 +139,26 @@ Numpad *******************************************--> - - -