1
0
Fork 0

fixed all alignment and size issues, especially on Android 15; got rid of the ConstraintLayout

This commit is contained in:
sspanak 2025-01-31 20:13:33 +02:00 committed by Dimo Karaivanov
parent b9ce74f254
commit d23efc4e60
9 changed files with 184 additions and 100 deletions

View file

@ -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'
}

View file

@ -20,13 +20,9 @@ public class ItemNumpadWidth extends ItemDropDown {
@Override
public ItemDropDown populate() {
LinkedHashMap<Integer, String> 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();

View file

@ -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() {

View file

@ -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;
}
/**
* Calculate the bottom padding for the edge-to-edge mode in 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;
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;
}
}
final int DEFAULT_SIZE = 96;
WindowInsets insets = tt9.getWindow().findViewById(android.R.id.content).getRootWindowInsets();
return insets != null ? insets.getStableInsetBottom() : DEFAULT_SIZE;
/**
* 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.
*/
@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);
}
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();

View file

@ -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();

View file

@ -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);

View file

@ -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() {

View file

@ -1,19 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/TTheme.Numpad.FullScreenAlignmentContainer"
android:id="@+id/numpad_container">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/TTheme.FullScreenContainer"
android:id="@+id/full_screen_container">
<androidx.constraintlayout.widget.ConstraintLayout
style="@style/TTheme.Numpad.FullScreenContainer"
android:id="@+id/numpad_width_constraint_wrapper">
<LinearLayout
style="@style/TTheme.Numpad"
android:id="@+id/linearLayout"
tools:ignore="MissingConstraints"> <!-- the constraints are set in the styles -->
<LinearLayout style="@style/TTheme.FullScreenContainer.SideBumper" android:id="@+id/numpad_bumper_left" />
<LinearLayout style="@style/TTheme.Numpad" android:id="@+id/numpad_container">
<View style="@style/TTheme.Keyboard.TopSeparator" />
<include layout="@layout/panel_numpad_status_bar" />
@ -28,7 +20,8 @@
<include layout="@layout/panel_numpad_text_editing" />
<include layout="@layout/panel_numpad_right" />
</LinearLayout>
</LinearLayout>
<LinearLayout style="@style/TTheme.FullScreenContainer.SideBumper" android:id="@+id/numpad_bumper_right" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>

View file

@ -139,29 +139,26 @@
Numpad
*******************************************-->
<!-- Full screen containers -->
<style name="TTheme.Numpad.FullScreenAlignmentContainer" parent="">
<style name="TTheme.FullScreenContainer" parent="">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">center_horizontal</item>
<item name="android:layoutDirection">ltr</item>
<item name="android:orientation">horizontal</item>
</style>
<style name="TTheme.Numpad.FullScreenContainer" parent="">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:maxWidth">@dimen/numpad_max_width</item>
<item name="layout_constraintStart_toStartOf">parent</item>
<item name="layout_constraintTop_toTopOf">parent</item>
<style name="TTheme.FullScreenContainer.SideBumper" parent="">
<item name="android:layout_height">1dp</item>
<item name="android:layout_width">0dp</item>
<item name="android:layout_weight">0</item>
<item name="android:layoutDirection">ltr</item>
<item name="android:orientation">horizontal</item>
</style>
<!-- The keyboard itself -->
<style name="TTheme.Numpad" parent="TTheme.Keyboard">
<item name="layout_constraintEnd_toEndOf">parent</item>
<item name="layout_constraintStart_toStartOf">parent</item>
<item name="layout_constraintTop_toTopOf">parent</item>
<item name="android:layoutDirection">ltr</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_width">0dp</item>
<item name="android:layout_weight">100</item>
<item name="android:orientation">vertical</item>
<item name="android:paddingBottom">@dimen/numpad_keys_spacing_bottom</item>
</style>