diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/fnKeyOrder/FnKeyOrderValidator.java b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/fnKeyOrder/FnKeyOrderValidator.java index 7f549649..ce5ab2ae 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/screens/fnKeyOrder/FnKeyOrderValidator.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/screens/fnKeyOrder/FnKeyOrderValidator.java @@ -46,7 +46,7 @@ public class FnKeyOrderValidator { private boolean validateLength(String text, int side) { - if (text == null || text.length() != 4) { + if (text == null || text.length() > 4) { error = R.string.fn_key_order_error_wrong_key_count; errorSide = side; return false; @@ -57,7 +57,7 @@ public class FnKeyOrderValidator { private boolean validateDigits(String text, int side) { - if (text == null || !text.matches("^[1-8]+$")) { + if (text == null || !text.matches("^[1-8]*$")) { error = R.string.fn_key_order_error_unsupported_key_code; errorSide = side; return false; diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsVirtualNumpad.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsVirtualNumpad.java index e387c9c6..fde08b97 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsVirtualNumpad.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsVirtualNumpad.java @@ -3,6 +3,8 @@ package io.github.sspanak.tt9.preferences.settings; import android.content.Context; import android.util.TypedValue; +import androidx.annotation.NonNull; + import java.util.HashMap; import io.github.sspanak.tt9.R; @@ -35,11 +37,11 @@ public class SettingsVirtualNumpad extends SettingsUI { return !prefs.getBoolean("pref_arrow_keys_visible", true); } - public String getLfnKeyOrder() { + @NonNull public String getLfnKeyOrder() { return prefs.getString("pref_lfn_key_order", DEFAULT_LFN_KEY_ORDER); } - public String getRfnKeyOrder() { + @NonNull public String getRfnKeyOrder() { return prefs.getString("pref_rfn_key_order", DEFAULT_RFN_KEY_ORDER); } 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 7c96f118..4abf7fb0 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 @@ -11,6 +11,7 @@ import android.view.WindowInsets; import android.widget.LinearLayout; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.view.WindowInsetsCompat; @@ -39,6 +40,24 @@ abstract class BaseMainLayout { } + protected void addKey(int keyId, @Nullable ViewGroup container) { + View source = container != null ? container : view; + if (source == null) { + return; + } + + SoftKey key = source.findViewById(keyId); + if (key != null) { + keys.add(key); + } + } + + + protected void addKey(int keyId) { + addKey(keyId, null); + } + + /** * getKeys * Returns a list of all the usable Soft Keys. Useful for attaching click handlers and changing 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 0e6e0861..58b5c622 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 @@ -116,9 +116,8 @@ class MainLayoutNumpad extends BaseMainLayout { * This prevents Android from auto-closing the keyboard in some apps that have a lot of content. * Returns the adjusted height of a single key. */ - private int calculateKeyHeight() { - int keyHeight = tt9.getSettings().getNumpadKeyHeight(); - boolean isLandscape = DeviceInfo.isLandscapeOrientation(tt9.getApplicationContext()); + private int[] calculateKeyHeight() { + final boolean isLandscape = DeviceInfo.isLandscapeOrientation(tt9.getApplicationContext()); int bottomPadding = 0; if (DeviceInfo.AT_LEAST_ANDROID_15) { @@ -126,21 +125,42 @@ class MainLayoutNumpad extends BaseMainLayout { bottomPadding = bottomPadding < 0 ? DeviceInfo.getNavigationBarHeight(tt9.getApplicationContext(), tt9.getSettings(), isLandscape) : bottomPadding; } - int screenHeight = DeviceInfo.getScreenHeight(tt9.getApplicationContext()) - bottomPadding; - double maxScreenHeight = isLandscape ? screenHeight * 0.6 : screenHeight * 0.75; - int maxKeyHeight = (int) Math.round(maxScreenHeight / 5); + final int screenHeight = DeviceInfo.getScreenHeight(tt9.getApplicationContext()) - bottomPadding; + final double maxScreenHeight = isLandscape ? screenHeight * 0.6 : screenHeight * 0.75; + final int maxKeyHeight = (int) Math.round(maxScreenHeight / 5); - return Math.min(keyHeight, maxKeyHeight); + final int defaultHeight = Math.min(tt9.getSettings().getNumpadKeyHeight(), maxKeyHeight); + + // in case some of the Fn keys are hidden, we need to stretch the rest + final int lfnCount = tt9.getSettings().getLfnKeyOrder().length(); + final int lfnHeight = lfnCount > 0 ? defaultHeight * 4 / lfnCount : defaultHeight; + + final int rfnCount = tt9.getSettings().getRfnKeyOrder().length(); + final int rfnHeight = rfnCount > 0 ? defaultHeight * 4 / rfnCount : defaultHeight; + + return new int[] {defaultHeight, lfnHeight, rfnHeight}; } - private void setKeyHeight(int height) { - if (view == null || height <= 0) { + private void setKeyHeight(int defaultHeight, int leftHeight, int rightHeight) { + if (view == null || defaultHeight <= 0) { return; } + final View leftColumn = view.findViewById(R.id.numpad_column_fn_left); + final View rightColumn = view.findViewById(R.id.numpad_column_fn_right); + for (SoftKey key : getKeys()) { - key.setHeight(height); + final View wrapper = (View) key.getParent(); + final View container = wrapper != null ? (View) wrapper.getParent() : null; + + if (container != null && container.equals(leftColumn)) { + key.setHeight(leftHeight); + } else if (container != null && container.equals(rightColumn)) { + key.setHeight(rightHeight); + } else { + key.setHeight(defaultHeight); + } } } @@ -180,7 +200,7 @@ class MainLayoutNumpad extends BaseMainLayout { 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) - + getKeyColumnHeight(calculateKeyHeight()) + + getKeyColumnHeight(calculateKeyHeight()[0]) + Math.round(resources.getDimension(R.dimen.numpad_keys_spacing_bottom)); } @@ -219,58 +239,53 @@ class MainLayoutNumpad extends BaseMainLayout { } // status bar - ViewGroup statusBar = view.findViewById(R.id.status_bar_container); - keys.add(statusBar.findViewById(R.id.soft_key_left_arrow)); - keys.add(statusBar.findViewById(R.id.soft_key_right_arrow)); - + keys.addAll(getKeysFromContainer(view.findViewById(R.id.status_bar_container))); // left Fn - keys.add(view.findViewById(R.id.soft_key_settings)); - keys.add(view.findViewById(R.id.soft_key_add_word)); - keys.add(view.findViewById(R.id.soft_key_shift)); - keys.add(view.findViewById(R.id.soft_key_lf4)); + addKey(R.id.soft_key_settings); + addKey(R.id.soft_key_add_word); + addKey(R.id.soft_key_shift); + addKey(R.id.soft_key_lf4); // right Fn - keys.add(view.findViewById(R.id.soft_key_numpad_backspace)); - keys.add(view.findViewById(R.id.soft_key_filter)); - keys.add(view.findViewById(R.id.soft_key_rf3)); - keys.add(view.findViewById(R.id.soft_key_numpad_ok)); + addKey(R.id.soft_key_numpad_backspace); + addKey(R.id.soft_key_filter); + addKey(R.id.soft_key_rf3); + addKey(R.id.soft_key_numpad_ok); // digits panel ViewGroup table = view.findViewById(R.id.main_soft_keys); - keys.add(table.findViewById(R.id.soft_key_0)); - keys.add(table.findViewById(R.id.soft_key_1)); - keys.add(table.findViewById(R.id.soft_key_2)); - keys.add(table.findViewById(R.id.soft_key_3)); - keys.add(table.findViewById(R.id.soft_key_4)); - keys.add(table.findViewById(R.id.soft_key_5)); - keys.add(table.findViewById(R.id.soft_key_6)); - keys.add(table.findViewById(R.id.soft_key_7)); - keys.add(table.findViewById(R.id.soft_key_8)); - keys.add(table.findViewById(R.id.soft_key_9)); - keys.add(table.findViewById(R.id.soft_key_punctuation_1)); - keys.add(table.findViewById(R.id.soft_key_punctuation_2)); + addKey(R.id.soft_key_0, table); + addKey(R.id.soft_key_1, table); + addKey(R.id.soft_key_2, table); + addKey(R.id.soft_key_3, table); + addKey(R.id.soft_key_4, table); + addKey(R.id.soft_key_5, table); + addKey(R.id.soft_key_6, table); + addKey(R.id.soft_key_7, table); + addKey(R.id.soft_key_8, table); + addKey(R.id.soft_key_9, table); + addKey(R.id.soft_key_punctuation_1, table); + addKey(R.id.soft_key_punctuation_2, table); // text editing panel - keys.add(table.findViewById(R.id.soft_key_100)); - keys.add(table.findViewById(R.id.soft_key_101)); - keys.add(table.findViewById(R.id.soft_key_102)); - keys.add(table.findViewById(R.id.soft_key_103)); - keys.add(table.findViewById(R.id.soft_key_104)); - keys.add(table.findViewById(R.id.soft_key_105)); - keys.add(table.findViewById(R.id.soft_key_106)); - keys.add(table.findViewById(R.id.soft_key_107)); - keys.add(table.findViewById(R.id.soft_key_108)); - keys.add(table.findViewById(R.id.soft_key_109)); - keys.add(table.findViewById(R.id.soft_key_punctuation_101)); - keys.add(table.findViewById(R.id.soft_key_punctuation_102)); + addKey(R.id.soft_key_100, table); + addKey(R.id.soft_key_101, table); + addKey(R.id.soft_key_102, table); + addKey(R.id.soft_key_103, table); + addKey(R.id.soft_key_104, table); + addKey(R.id.soft_key_105, table); + addKey(R.id.soft_key_106, table); + addKey(R.id.soft_key_107, table); + addKey(R.id.soft_key_108, table); + addKey(R.id.soft_key_109, table); + addKey(R.id.soft_key_punctuation_101, table); + addKey(R.id.soft_key_punctuation_102, table); // Long space panel - keys.add(table.findViewById(R.id.soft_key_200)); - keys.add(table.findViewById(R.id.soft_key_punctuation_201)); - keys.add(table.findViewById(R.id.soft_key_punctuation_202)); - - keys.addAll(getKeysFromContainer(view.findViewById(R.id.status_bar_container))); + addKey(R.id.soft_key_200, table); + addKey(R.id.soft_key_punctuation_201, table); + addKey(R.id.soft_key_punctuation_202, table); return keys; } @@ -302,6 +317,7 @@ class MainLayoutNumpad extends BaseMainLayout { keyWrappers.put(entry.getValue(), view.findViewById(entry.getValue())); } + hideUnusedFnKeys(keyWrappers, lfnOrder, rfnOrder); reorderFnColumn(left, lfnOrder, keyWrappers); reorderFnColumn(right, rfnOrder, keyWrappers); @@ -310,7 +326,29 @@ class MainLayoutNumpad extends BaseMainLayout { } - private void reorderFnColumn(ViewGroup column, String order, Map keyWrappers) { + private void hideUnusedFnKeys(@NonNull Map keyWrappers, @NonNull String leftOrder, @NonNull String rightOrder) { + for (Map.Entry entry : keyWrappers.entrySet()) { + Integer keyId = entry.getKey(); + View key = entry.getValue(); + + if (key != null && leftOrder.indexOf(keyId) < 0 && rightOrder.indexOf(keyId) < 0) { + key.setVisibility(View.GONE); + } + } + + View leftColumn = view.findViewById(R.id.numpad_column_fn_left); + if (leftColumn != null) { + leftColumn.setVisibility(leftOrder.isEmpty() ? View.GONE : View.VISIBLE); + } + + View rightColumn = view.findViewById(R.id.numpad_column_fn_right); + if (rightColumn != null) { + rightColumn.setVisibility(rightOrder.isEmpty() ? View.GONE : View.VISIBLE); + } + } + + + private void reorderFnColumn(@NonNull ViewGroup column, @NonNull String order, @NonNull Map keyWrappers) { for (char keyId : order.toCharArray()) { Integer viewId = SettingsVirtualNumpad.KEY_ORDER_MAP.get(keyId); if (viewId == null) { @@ -325,18 +363,19 @@ class MainLayoutNumpad extends BaseMainLayout { ((ViewGroup) key.getParent()).removeView(key); column.addView(key); + key.setVisibility(View.VISIBLE); } } @Override void render() { - int defaultKeyHeight = calculateKeyHeight(); + final int[] keyHeights = calculateKeyHeight(); getView(); reorderFnKeys(); enableClickHandlers(); - setKeyHeight(defaultKeyHeight); + setKeyHeight(keyHeights[0], keyHeights[1], keyHeights[2]); preventEdgeToEdge(); setWidth(tt9.getSettings().getWidthPercent(), tt9.getSettings().getAlignment()); setKeyColumnWidth(tt9.getSettings().getNumpadFnKeyScale()); @@ -345,7 +384,7 @@ class MainLayoutNumpad extends BaseMainLayout { boolean hasLettersOnAllKeys = tt9.getLanguage() != null && tt9.getLanguage().hasLettersOnAllKeys(); showLongSpace( tt9.getSettings().isNumpadShapeLongSpace() && !tt9.isInputModeNumeric() && !hasLettersOnAllKeys, - defaultKeyHeight + keyHeights[0] ); for (SoftKey key : getKeys()) { diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index c59f19b7..a74f5e74 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -221,7 +221,7 @@ Отмяна (Undo) Преизчисли долното отстояние Колона 2 - Трябва да има точно по 4 клавиша в колона. + Колоната може да съдържа най-много 4 клавиша. Разрешени са само кодове на клавиши от 1 до 8. Един клавиш не може да бъде поставен и в двете колони. Колона 1 diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index cb267f4b..d77392fd 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -223,7 +223,7 @@ Rückgängig machen Unteren Abstand neu berechnen Spalte 2 - Es müssen genau 4 Tasten pro Spalte sein. + Die Spalte darf höchstens 4 Tasten enthalten. Nur Tastencodes 1–8 sind erlaubt. Eine Taste kann nicht in beiden Spalten platziert werden. Spalte 1 diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 23cc7a9e..f57c45e9 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -221,7 +221,7 @@ Deshacer Recalcular el relleno inferior Columna 2 - Debe haber exactamente 4 teclas por columna. + La columna puede contener como máximo 4 teclas. Solo se permiten los códigos de tecla del 1 al 8. Una tecla no puede colocarse en ambas columnas. Columna 1 diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 09a255e4..6918df4c 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -221,7 +221,7 @@ Annuler (Undo) Recalculer le remplissage inférieur Colonne 2 - Il doit y avoir exactement 4 touches par colonne. + La colonne peut contenir au maximum 4 touches. Seuls les codes de touche 1 à 8 sont autorisés. Une touche ne peut pas être placée dans les deux colonnes. Colonne 1 diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 9cf00f0d..c95151a4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -224,7 +224,7 @@ Annulla (Undo) Ricalcola il margine inferiore Colonna 2 - Devono esserci esattamente 4 tasti per colonna. + La colonna può contenere al massimo 4 tasti. Sono consentiti solo i codici dei tasti da 1 a 8. Un tasto non può essere inserito in entrambe le colonne. Colonna 1 diff --git a/app/src/main/res/values-iw/strings.xml b/app/src/main/res/values-iw/strings.xml index 39849d57..e91c76f1 100644 --- a/app/src/main/res/values-iw/strings.xml +++ b/app/src/main/res/values-iw/strings.xml @@ -228,7 +228,7 @@ ביטול (Undo) חשב מחדש ריווח תחתון עמודה 2 - חייבים להיות בדיוק 4 מקשים בכל עמודה. + העמודה יכולה להכיל לכל היותר 4 מקשים. רק קודי מקשים 1–8 מותרים. לא ניתן למקם מקש אחד בשתי העמודות. עמודה 1 diff --git a/app/src/main/res/values-lt/strings.xml b/app/src/main/res/values-lt/strings.xml index 36b063bb..e6bf7d71 100644 --- a/app/src/main/res/values-lt/strings.xml +++ b/app/src/main/res/values-lt/strings.xml @@ -230,7 +230,7 @@ Atšaukti (Undo) Perskaičiuoti apatinį paraštę Stulpelis 2 - Kiekvienoje stulpelyje turi būti tiksliai 4 klavišai. + Stulpelyje gali būti daugiausiai 4 klavišai. Leidžiami tik klavišų kodai nuo 1 iki 8. Vieno klavišo negalima dėti į abu stulpelius. Stulpelis 1 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index c8f4a3c5..e9f449db 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -222,7 +222,7 @@ Ongedaan maken Onderrand opnieuw berekenen Kolom 2 - Er moeten precies 4 toetsen per kolom zijn. + De kolom mag maximaal 4 toetsen bevatten. Alleen toetscodes 1–8 zijn toegestaan. Eén toets kan niet in beide kolommen staan. Kolom 1 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 2650c0d8..6bb07d9e 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -228,7 +228,7 @@ Desfazer Recalcular o espaçamento inferior Coluna 2 - Deve haver exatamente 4 teclas por coluna. + A coluna pode conter no máximo 4 teclas. Apenas os códigos de tecla de 1 a 8 são permitidos. Uma tecla não pode estar nas duas colunas. Coluna 1 diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 9e248e0b..fd1c18c8 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -221,7 +221,7 @@ Отменить (Undo) Пересчитать нижний отступ Столбец 2 - В каждой колонке должно быть ровно 4 клавиши. + В столбце может быть не более 4 клавиш. Разрешены только коды клавиш от 1 до 8. Одна клавиша не может находиться в обеих колонках. Столбец 1 diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 1fee8058..e5fd8ee0 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -226,7 +226,7 @@ Geri al (Undo) Alt boşluğu yeniden hesapla Sütun 2 - Her sütunda tam olarak 4 tuş olmalıdır. + Sütun en fazla 4 tuş içerebilir. Yalnızca 1–8 arası tuş kodlarına izin verilir. Bir tuş her iki sütuna da yerleştirilemez. Sütun 1 diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 0d3bce5a..ee4c93c0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -232,7 +232,7 @@ Скасувати (Undo) Перерахувати нижній відступ Стовпець 2 - У кожному стовпці має бути рівно 4 клавіші. + У стовпці може бути щонайбільше 4 клавіші. Дозволено лише коди клавіш від 1 до 8. Одна клавіша не може бути в обох стовпцях. Стовпець 1 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2393cc0f..55202acb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -164,7 +164,7 @@ Column 1 Column 2 - There must be exactly 4 keys per column. + The column can contain at most 4 keys. Only key codes 1–8 are allowed. One key cannot be placed in both columns. No duplicate keys allowed.