UI resize
This commit is contained in:
parent
2bfabd2ec8
commit
867b3be578
31 changed files with 602 additions and 59 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:tools="http://schemas.android.com/tools"
|
<manifest xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:versionCode="573"
|
android:versionCode="580"
|
||||||
android:versionName="34.0"
|
android:versionName="34.7"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 -->
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 -->
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ime;
|
package io.github.sspanak.tt9.ime;
|
||||||
|
|
||||||
import android.inputmethodservice.InputMethodService;
|
import android.inputmethodservice.InputMethodService;
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
|
|
@ -24,7 +23,7 @@ abstract public class AbstractHandler extends InputMethodService {
|
||||||
abstract protected void setInputField(InputConnection inputConnection, EditorInfo inputField);
|
abstract protected void setInputField(InputConnection inputConnection, EditorInfo inputField);
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
abstract protected void createSuggestionBar(View mainView);
|
abstract protected void createSuggestionBar();
|
||||||
abstract protected void resetStatus();
|
abstract protected void resetStatus();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import io.github.sspanak.tt9.ime.modes.ModeABC;
|
||||||
import io.github.sspanak.tt9.ime.voice.VoiceInputOps;
|
import io.github.sspanak.tt9.ime.voice.VoiceInputOps;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
|
|
||||||
abstract public class MainViewHandler extends HotkeyHandler {
|
abstract public class MainViewHandler extends HotkeyHandler {
|
||||||
/**** Informational methods for the on-screen keyboard ****/
|
/**** Informational methods for the on-screen keyboard ****/
|
||||||
|
|
@ -46,6 +47,10 @@ abstract public class MainViewHandler extends HotkeyHandler {
|
||||||
return mLanguage;
|
return mLanguage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ResizableMainView getMainView() {
|
||||||
|
return mainView;
|
||||||
|
}
|
||||||
|
|
||||||
public SettingsStore getSettings() {
|
public SettingsStore getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ime;
|
package io.github.sspanak.tt9.ime;
|
||||||
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.View;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
|
|
||||||
|
|
@ -42,8 +41,8 @@ public abstract class TypingHandler extends KeyPadHandler {
|
||||||
protected Language mLanguage;
|
protected Language mLanguage;
|
||||||
|
|
||||||
|
|
||||||
protected void createSuggestionBar(View mainView) {
|
protected void createSuggestionBar() {
|
||||||
suggestionOps = new SuggestionOps(settings, mainView, this::onAcceptSuggestionsDelayed, this::onOK);
|
suggestionOps = new SuggestionOps(settings, mainView, textField, this::onAcceptSuggestionsDelayed, this::onOK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,19 +7,19 @@ import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.hacks.DeviceInfo;
|
import io.github.sspanak.tt9.hacks.DeviceInfo;
|
||||||
import io.github.sspanak.tt9.ime.modes.InputMode;
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
import io.github.sspanak.tt9.ui.main.MainView;
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
import io.github.sspanak.tt9.ui.tray.StatusBar;
|
import io.github.sspanak.tt9.ui.tray.StatusBar;
|
||||||
|
|
||||||
abstract class UiHandler extends AbstractHandler {
|
abstract class UiHandler extends AbstractHandler {
|
||||||
protected SettingsStore settings;
|
protected SettingsStore settings;
|
||||||
protected MainView mainView = null;
|
protected ResizableMainView mainView = null;
|
||||||
protected StatusBar statusBar = null;
|
protected StatusBar statusBar = null;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onInit() {
|
protected void onInit() {
|
||||||
if (mainView == null) {
|
if (mainView == null) {
|
||||||
mainView = new MainView(getFinalContext());
|
mainView = new ResizableMainView(getFinalContext());
|
||||||
initTray();
|
initTray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -27,12 +27,12 @@ abstract class UiHandler extends AbstractHandler {
|
||||||
|
|
||||||
protected void initTray() {
|
protected void initTray() {
|
||||||
setInputView(mainView.getView());
|
setInputView(mainView.getView());
|
||||||
createSuggestionBar(mainView.getView());
|
createSuggestionBar();
|
||||||
statusBar = new StatusBar(mainView.getView());
|
statusBar = new StatusBar(mainView.getView());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void initUi() {
|
public void initUi() {
|
||||||
if (mainView.createInputView()) {
|
if (mainView.createInputView()) {
|
||||||
initTray();
|
initTray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ package io.github.sspanak.tt9.ime.helpers;
|
||||||
|
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
|
import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
|
||||||
import io.github.sspanak.tt9.util.ConsumerCompat;
|
import io.github.sspanak.tt9.util.ConsumerCompat;
|
||||||
|
|
||||||
|
|
@ -19,12 +19,12 @@ public class SuggestionOps {
|
||||||
@NonNull private TextField textField;
|
@NonNull private TextField textField;
|
||||||
|
|
||||||
|
|
||||||
public SuggestionOps(@NonNull SettingsStore settings, View mainView, @NonNull ConsumerCompat<String> onDelayedAccept, @NonNull Runnable onSuggestionClick) {
|
public SuggestionOps(@NonNull SettingsStore settings, @NonNull ResizableMainView mainView, @NonNull TextField textField, @NonNull ConsumerCompat<String> onDelayedAccept, @NonNull Runnable onSuggestionClick) {
|
||||||
delayedAcceptHandler = new Handler(Looper.getMainLooper());
|
delayedAcceptHandler = new Handler(Looper.getMainLooper());
|
||||||
this.onDelayedAccept = onDelayedAccept;
|
this.onDelayedAccept = onDelayedAccept;
|
||||||
|
|
||||||
suggestionBar = new SuggestionsBar(settings, mainView, onSuggestionClick);
|
suggestionBar = new SuggestionsBar(settings, mainView, onSuggestionClick);
|
||||||
textField = new TextField(null, null);
|
this.textField = textField;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import java.util.LinkedHashMap;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
abstract public class ItemDropDown {
|
abstract public class ItemDropDown {
|
||||||
private final DropDownPreference item;
|
protected final DropDownPreference item;
|
||||||
private LinkedHashMap<String, String> values;
|
private LinkedHashMap<String, String> values;
|
||||||
|
|
||||||
public ItemDropDown(DropDownPreference item) {
|
public ItemDropDown(DropDownPreference item) {
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,18 @@ public class AppearanceScreen extends BaseScreenFragment {
|
||||||
(new ItemStatusIcon(findPreference(ItemStatusIcon.NAME), activity.getSettings())).populate();
|
(new ItemStatusIcon(findPreference(ItemStatusIcon.NAME), activity.getSettings())).populate();
|
||||||
ItemHapticFeedback hapticFeedback = (new ItemHapticFeedback(findPreference(ItemHapticFeedback.NAME), activity.getSettings())).populate();
|
ItemHapticFeedback hapticFeedback = (new ItemHapticFeedback(findPreference(ItemHapticFeedback.NAME), activity.getSettings())).populate();
|
||||||
|
|
||||||
|
ItemNumpadKeyHeight numpadKeyHeight = new ItemNumpadKeyHeight(findPreference(ItemNumpadKeyHeight.NAME), activity.getSettings());
|
||||||
ItemDropDown[] items = {
|
ItemDropDown[] items = {
|
||||||
new ItemSelectTheme(findPreference(ItemSelectTheme.NAME), activity),
|
new ItemSelectTheme(findPreference(ItemSelectTheme.NAME), activity),
|
||||||
new ItemSelectLayoutType(findPreference(ItemSelectLayoutType.NAME), activity, hapticFeedback::populate),
|
new ItemSelectLayoutType(
|
||||||
new ItemSelectSettingsFontSize(findPreference(ItemSelectSettingsFontSize.NAME), this)
|
findPreference(ItemSelectLayoutType.NAME),
|
||||||
|
activity,
|
||||||
|
(layout) -> {
|
||||||
|
hapticFeedback.onLayoutChange(layout);
|
||||||
|
numpadKeyHeight.onLayoutChange(layout);
|
||||||
|
}),
|
||||||
|
new ItemSelectSettingsFontSize(findPreference(ItemSelectSettingsFontSize.NAME), this),
|
||||||
|
numpadKeyHeight
|
||||||
};
|
};
|
||||||
|
|
||||||
for (ItemDropDown item : items) {
|
for (ItemDropDown item : items) {
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,14 @@ class ItemHapticFeedback extends ItemClickable {
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemHapticFeedback populate() {
|
ItemHapticFeedback populate() {
|
||||||
return populate(settings.getMainViewLayout());
|
onLayoutChange(settings.getMainViewLayout());
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onLayoutChange(int mainViewLayout) {
|
||||||
ItemHapticFeedback populate(int mainViewLayout) {
|
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
item.setEnabled(mainViewLayout == SettingsStore.LAYOUT_NUMPAD || mainViewLayout == SettingsStore.LAYOUT_SMALL);
|
item.setEnabled(mainViewLayout == SettingsStore.LAYOUT_NUMPAD || mainViewLayout == SettingsStore.LAYOUT_SMALL);
|
||||||
((SwitchPreferenceCompat) item).setChecked(settings.getHapticFeedback());
|
((SwitchPreferenceCompat) item).setChecked(settings.getHapticFeedback());
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package io.github.sspanak.tt9.preferences.screens.appearance;
|
||||||
|
|
||||||
|
import androidx.preference.DropDownPreference;
|
||||||
|
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.preferences.items.ItemDropDown;
|
||||||
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
|
||||||
|
public class ItemNumpadKeyHeight extends ItemDropDown {
|
||||||
|
public static final String NAME = "pref_numpad_key_height";
|
||||||
|
|
||||||
|
private final SettingsStore settings;
|
||||||
|
|
||||||
|
public ItemNumpadKeyHeight(DropDownPreference item, SettingsStore settings) {
|
||||||
|
super(item);
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemDropDown populate() {
|
||||||
|
int baseSize = settings.getNumpadKeyDefaultHeight();
|
||||||
|
|
||||||
|
LinkedHashMap<Integer, String> options = new LinkedHashMap<>();
|
||||||
|
options.put((int) Math.round(baseSize * 0.7), "70 %");
|
||||||
|
options.put((int) Math.round(baseSize * 0.75), "75 %");
|
||||||
|
options.put((int) Math.round(baseSize * 0.8), "80 %");
|
||||||
|
options.put((int) Math.round(baseSize * 0.85), "85 %");
|
||||||
|
options.put((int) Math.round(baseSize * 0.9), "90 %");
|
||||||
|
options.put((int) Math.round(baseSize * 0.95), "95 %");
|
||||||
|
options.put(baseSize, "100 %");
|
||||||
|
options.put((int) Math.round(baseSize * 1.1), "110 %");
|
||||||
|
options.put((int) Math.round(baseSize * 1.2), "120 %");
|
||||||
|
options.put((int) Math.round(baseSize * 1.33), "133 %");
|
||||||
|
|
||||||
|
super.populateIntegers(options);
|
||||||
|
super.setValue(settings.getNumpadKeyHeight() + "");
|
||||||
|
onLayoutChange(settings.getMainViewLayout());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onLayoutChange(int mainViewLayout) {
|
||||||
|
if (item != null) {
|
||||||
|
item.setEnabled(mainViewLayout == SettingsStore.LAYOUT_NUMPAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,9 @@ public class SettingsStore extends SettingsUI {
|
||||||
public final static int DICTIONARY_DOWNLOAD_READ_TIMEOUT = 10000; // ms
|
public final static int DICTIONARY_DOWNLOAD_READ_TIMEOUT = 10000; // ms
|
||||||
public final static int DICTIONARY_IMPORT_BATCH_SIZE = 5000; // words
|
public final static int DICTIONARY_IMPORT_BATCH_SIZE = 5000; // words
|
||||||
public final static int DICTIONARY_IMPORT_PROGRESS_UPDATE_TIME = 250; // ms
|
public final static int DICTIONARY_IMPORT_PROGRESS_UPDATE_TIME = 250; // ms
|
||||||
|
public final static int RESIZE_THROTTLING_TIME = 60; // ms
|
||||||
public final static byte SLOW_QUERY_TIME = 50; // ms
|
public final static byte SLOW_QUERY_TIME = 50; // ms
|
||||||
|
public final static int SOFT_KEY_DOUBLE_CLICK_DELAY = 500; // ms
|
||||||
public final static int SOFT_KEY_REPEAT_DELAY = 40; // ms
|
public final static int SOFT_KEY_REPEAT_DELAY = 40; // ms
|
||||||
public final static int SOFT_KEY_TITLE_SIZE = 18; // sp
|
public final static int SOFT_KEY_TITLE_SIZE = 18; // sp
|
||||||
public final static float SOFT_KEY_COMPLEX_LABEL_TITLE_RELATIVE_SIZE = 0.55f;
|
public final static float SOFT_KEY_COMPLEX_LABEL_TITLE_RELATIVE_SIZE = 0.55f;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,9 @@ import android.content.res.Configuration;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
import androidx.appcompat.app.AppCompatDelegate;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.hacks.DeviceInfo;
|
import io.github.sspanak.tt9.hacks.DeviceInfo;
|
||||||
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class SettingsUI extends SettingsTyping {
|
public class SettingsUI extends SettingsTyping {
|
||||||
public final static int FONT_SIZE_DEFAULT = 0;
|
public final static int FONT_SIZE_DEFAULT = 0;
|
||||||
|
|
@ -36,6 +38,14 @@ public class SettingsUI extends SettingsTyping {
|
||||||
return prefs.getBoolean("pref_haptic_feedback", true);
|
return prefs.getBoolean("pref_haptic_feedback", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getNumpadKeyDefaultHeight() {
|
||||||
|
return context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumpadKeyHeight() {
|
||||||
|
return getStringifiedInt("pref_numpad_key_height", getNumpadKeyDefaultHeight());
|
||||||
|
}
|
||||||
|
|
||||||
public int getSettingsFontSize() {
|
public int getSettingsFontSize() {
|
||||||
int defaultSize = DeviceInfo.isQinF21() || DeviceInfo.isLgX100S() ? FONT_SIZE_LARGE : FONT_SIZE_DEFAULT;
|
int defaultSize = DeviceInfo.isQinF21() || DeviceInfo.isLgX100S() ? FONT_SIZE_LARGE : FONT_SIZE_DEFAULT;
|
||||||
return getStringifiedInt("pref_font_size", defaultSize);
|
return getStringifiedInt("pref_font_size", defaultSize);
|
||||||
|
|
@ -45,6 +55,16 @@ public class SettingsUI extends SettingsTyping {
|
||||||
return getStringifiedInt("pref_theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
return getStringifiedInt("pref_theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMainViewLayout(int layout) {
|
||||||
|
if (layout != LAYOUT_STEALTH && layout != LAYOUT_TRAY && layout != LAYOUT_SMALL && layout != LAYOUT_NUMPAD) {
|
||||||
|
Logger.w(getClass().getSimpleName(), "Ignoring invalid main view layout: " + layout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefsEditor.putString("pref_layout_type", Integer.toString(layout));
|
||||||
|
prefsEditor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public int getMainViewLayout() {
|
public int getMainViewLayout() {
|
||||||
int defaultLayout = LAYOUT_SMALL;
|
int defaultLayout = LAYOUT_SMALL;
|
||||||
if (DeviceInfo.noTouchScreen(context)) {
|
if (DeviceInfo.noTouchScreen(context)) {
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,12 @@ abstract class BaseMainLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getHeight() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetHeight() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* render
|
* render
|
||||||
* Do all the necessary stuff to display the View.
|
* Do all the necessary stuff to display the View.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ui.main;
|
package io.github.sspanak.tt9.ui.main;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
|
@ -12,8 +13,12 @@ import java.util.Arrays;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||||
|
import io.github.sspanak.tt9.ui.main.keys.SoftKeySettings;
|
||||||
|
|
||||||
class MainLayoutNumpad extends BaseMainLayout {
|
class MainLayoutNumpad extends BaseMainLayout {
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
|
||||||
MainLayoutNumpad(TraditionalT9 tt9) {
|
MainLayoutNumpad(TraditionalT9 tt9) {
|
||||||
super(tt9, R.layout.main_numpad);
|
super(tt9, R.layout.main_numpad);
|
||||||
}
|
}
|
||||||
|
|
@ -34,6 +39,7 @@ class MainLayoutNumpad extends BaseMainLayout {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void setDarkTheme(boolean dark) {
|
void setDarkTheme(boolean dark) {
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
|
|
@ -57,15 +63,66 @@ class MainLayoutNumpad extends BaseMainLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setKeyHeight(int height) {
|
||||||
|
if (view == null || height <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewGroup table = view.findViewById(R.id.main_soft_keys);
|
||||||
|
int tableRowsCount = table.getChildCount();
|
||||||
|
|
||||||
|
for (int rowId = 0; rowId < tableRowsCount; rowId++) {
|
||||||
|
View row = table.getChildAt(rowId);
|
||||||
|
ViewGroup.LayoutParams layout = row.getLayoutParams();
|
||||||
|
if (layout != null) {
|
||||||
|
layout.height = height;
|
||||||
|
row.setLayoutParams(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int getHeight() {
|
||||||
|
if (height <= 0) {
|
||||||
|
Resources resources = tt9.getResources();
|
||||||
|
height = tt9.getSettings().getNumpadKeyHeight() * 4
|
||||||
|
+ resources.getDimensionPixelSize(R.dimen.numpad_candidate_height)
|
||||||
|
+ resources.getDimensionPixelSize(R.dimen.numpad_padding_bottom) * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resetHeight() {
|
||||||
|
height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void render() {
|
void render() {
|
||||||
getView();
|
getView();
|
||||||
|
setKeyHeight(tt9 != null ? tt9.getSettings().getNumpadKeyHeight() : -1);
|
||||||
enableClickHandlers();
|
enableClickHandlers();
|
||||||
for (SoftKey key : getKeys()) {
|
for (SoftKey key : getKeys()) {
|
||||||
key.render();
|
key.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enableClickHandlers() {
|
||||||
|
super.enableClickHandlers();
|
||||||
|
|
||||||
|
for (SoftKey key : getKeys()) {
|
||||||
|
if (key instanceof SoftKeySettings) {
|
||||||
|
((SoftKeySettings) key).setMainView(tt9.getMainView());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected ArrayList<SoftKey> getKeys() {
|
protected ArrayList<SoftKey> getKeys() {
|
||||||
|
|
@ -89,6 +146,7 @@ class MainLayoutNumpad extends BaseMainLayout {
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected ArrayList<View> getSeparators() {
|
protected ArrayList<View> getSeparators() {
|
||||||
// it's fine... it's shorter, faster and easier to read than searching with 3 nested loops
|
// it's fine... it's shorter, faster and easier to read than searching with 3 nested loops
|
||||||
return new ArrayList<>(Arrays.asList(
|
return new ArrayList<>(Arrays.asList(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ui.main;
|
package io.github.sspanak.tt9.ui.main;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
||||||
|
|
@ -10,12 +11,25 @@ import java.util.ArrayList;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||||
|
import io.github.sspanak.tt9.ui.main.keys.SoftKeyCommandPalette;
|
||||||
|
|
||||||
class MainLayoutSmall extends MainLayoutTray {
|
class MainLayoutSmall extends MainLayoutTray {
|
||||||
|
private int height;
|
||||||
|
|
||||||
MainLayoutSmall(TraditionalT9 tt9) {
|
MainLayoutSmall(TraditionalT9 tt9) {
|
||||||
super(tt9);
|
super(tt9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getHeight() {
|
||||||
|
if (height <= 0) {
|
||||||
|
Resources resources = tt9.getResources();
|
||||||
|
height =
|
||||||
|
resources.getDimensionPixelSize(R.dimen.soft_key_height) +
|
||||||
|
resources.getDimensionPixelSize(R.dimen.candidate_height);
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setSoftKeysVisibility() {
|
protected void setSoftKeysVisibility() {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
|
|
@ -23,6 +37,17 @@ class MainLayoutSmall extends MainLayoutTray {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void enableClickHandlers() {
|
||||||
|
super.enableClickHandlers();
|
||||||
|
|
||||||
|
for (SoftKey key : getKeys()) {
|
||||||
|
if (key instanceof SoftKeyCommandPalette) {
|
||||||
|
((SoftKeyCommandPalette) key).setMainView(tt9.getMainView());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
protected ArrayList<SoftKey> getKeys() {
|
protected ArrayList<SoftKey> getKeys() {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package io.github.sspanak.tt9.ui.main;
|
package io.github.sspanak.tt9.ui.main;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
|
@ -15,10 +16,20 @@ import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||||
|
|
||||||
class MainLayoutTray extends BaseMainLayout {
|
class MainLayoutTray extends BaseMainLayout {
|
||||||
|
private int height;
|
||||||
|
|
||||||
MainLayoutTray(TraditionalT9 tt9) {
|
MainLayoutTray(TraditionalT9 tt9) {
|
||||||
super(tt9, R.layout.main_small);
|
super(tt9, R.layout.main_small);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getHeight() {
|
||||||
|
if (height <= 0) {
|
||||||
|
Resources resources = tt9.getResources();
|
||||||
|
height = resources.getDimensionPixelSize(R.dimen.candidate_height);
|
||||||
|
}
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setSoftKeysVisibility() {
|
protected void setSoftKeysVisibility() {
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
view.findViewById(R.id.main_soft_keys).setVisibility(LinearLayout.GONE);
|
view.findViewById(R.id.main_soft_keys).setVisibility(LinearLayout.GONE);
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class MainView {
|
public class MainView {
|
||||||
private final TraditionalT9 tt9;
|
protected final TraditionalT9 tt9;
|
||||||
private BaseMainLayout main;
|
protected BaseMainLayout main;
|
||||||
|
|
||||||
public MainView(TraditionalT9 tt9) {
|
|
||||||
|
protected MainView(TraditionalT9 tt9) {
|
||||||
this.tt9 = tt9;
|
this.tt9 = tt9;
|
||||||
|
|
||||||
forceCreateInputView();
|
forceCreateInputView();
|
||||||
|
|
@ -32,6 +33,7 @@ public class MainView {
|
||||||
}
|
}
|
||||||
|
|
||||||
main.render();
|
main.render();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
package io.github.sspanak.tt9.ui.main;
|
||||||
|
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
|
||||||
|
public class ResizableMainView extends MainView implements View.OnAttachStateChangeListener {
|
||||||
|
private int height;
|
||||||
|
private float resizeStartY;
|
||||||
|
private long lastResizeTime;
|
||||||
|
|
||||||
|
private int heightNumpad;
|
||||||
|
private int heightSmall;
|
||||||
|
private int heightTray;
|
||||||
|
|
||||||
|
|
||||||
|
public ResizableMainView(TraditionalT9 tt9) {
|
||||||
|
super(tt9);
|
||||||
|
resetHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void calculateSnapHeights() {
|
||||||
|
heightNumpad = new MainLayoutNumpad(tt9).getHeight();
|
||||||
|
heightSmall = new MainLayoutSmall(tt9).getHeight();
|
||||||
|
heightTray = new MainLayoutTray(tt9).getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void calculateInitialHeight() {
|
||||||
|
if (main == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tt9.getSettings().isMainLayoutNumpad()) {
|
||||||
|
height = heightNumpad;
|
||||||
|
} else if (tt9.getSettings().isMainLayoutSmall()) {
|
||||||
|
height = heightSmall;
|
||||||
|
} else {
|
||||||
|
height = heightTray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean createInputView() {
|
||||||
|
|
||||||
|
if (!super.createInputView()) {
|
||||||
|
// recalculate the total height in case the user has changed the key height in the settings
|
||||||
|
resetHeight();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
main.getView().removeOnAttachStateChangeListener(this);
|
||||||
|
main.getView().addOnAttachStateChangeListener(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void onCreateAdjustHeight() {
|
||||||
|
if (tt9.getSettings().isMainLayoutNumpad() && height > heightSmall && height <= heightNumpad) {
|
||||||
|
setHeight(height, heightSmall, heightNumpad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onResizeStart(float startY) {
|
||||||
|
resizeStartY = startY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onResize(float currentY) {
|
||||||
|
int resizeDelta = (int) (resizeStartY - currentY);
|
||||||
|
resizeStartY = currentY;
|
||||||
|
|
||||||
|
if (resizeDelta < 0) {
|
||||||
|
shrink(resizeDelta);
|
||||||
|
} else if (resizeDelta > 0) {
|
||||||
|
expand(resizeDelta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onSnap() {
|
||||||
|
SettingsStore settings = tt9.getSettings();
|
||||||
|
|
||||||
|
if (settings.isMainLayoutTray()) {
|
||||||
|
expand(1);
|
||||||
|
} else if (settings.isMainLayoutSmall()) {
|
||||||
|
expand(heightNumpad);
|
||||||
|
} else {
|
||||||
|
shrink(-heightNumpad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void onResizeThrottled(float currentY) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now - lastResizeTime > SettingsStore.RESIZE_THROTTLING_TIME) {
|
||||||
|
lastResizeTime = now;
|
||||||
|
onResize(currentY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void expand(int delta) {
|
||||||
|
SettingsStore settings = tt9.getSettings();
|
||||||
|
|
||||||
|
if (settings.isMainLayoutTray()) {
|
||||||
|
settings.setMainViewLayout(SettingsStore.LAYOUT_SMALL);
|
||||||
|
height = heightSmall;
|
||||||
|
tt9.onCreateInputView();
|
||||||
|
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();
|
||||||
|
vibrate();
|
||||||
|
} else {
|
||||||
|
changeHeight(delta, heightSmall, heightNumpad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void shrink(int delta) {
|
||||||
|
SettingsStore settings = tt9.getSettings();
|
||||||
|
|
||||||
|
if (settings.isMainLayoutTray()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.isMainLayoutSmall()) {
|
||||||
|
settings.setMainViewLayout(SettingsStore.LAYOUT_TRAY);
|
||||||
|
height = heightTray;
|
||||||
|
tt9.onCreateInputView();
|
||||||
|
vibrate();
|
||||||
|
} else if (!changeHeight(delta, heightSmall, heightNumpad)) {
|
||||||
|
settings.setMainViewLayout(SettingsStore.LAYOUT_SMALL);
|
||||||
|
height = heightSmall;
|
||||||
|
tt9.onCreateInputView();
|
||||||
|
vibrate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean changeHeight(int delta, int minHeight, int maxHeight) {
|
||||||
|
if (main == null || main.getView() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setHeight(main.getView().getMeasuredHeight() + delta, minHeight, maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean setHeight(int height, int minHeight, int maxHeight) {
|
||||||
|
if (main == null || main.getView() == null || height < minHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
height = Math.min(height, maxHeight);
|
||||||
|
|
||||||
|
ViewGroup.LayoutParams params = main.getView().getLayoutParams();
|
||||||
|
if (params == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params.height = height;
|
||||||
|
main.getView().setLayoutParams(params);
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void resetHeight() {
|
||||||
|
if (main != null) {
|
||||||
|
main.resetHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateSnapHeights();
|
||||||
|
calculateInitialHeight();
|
||||||
|
setHeight(height, heightSmall, heightNumpad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void vibrate() {
|
||||||
|
if (tt9.getSettings().getHapticFeedback() && main != null && main.getView() != null) {
|
||||||
|
main.getView().performHapticFeedback(Vibration.getPressVibration(null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override public void onViewAttachedToWindow(@NonNull View v) { onCreateAdjustHeight(); }
|
||||||
|
@Override public void onViewDetachedFromWindow(@NonNull View v) {}
|
||||||
|
}
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
package io.github.sspanak.tt9.ui.main.keys;
|
package io.github.sspanak.tt9.ui.main;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.HapticFeedbackConstants;
|
import android.view.HapticFeedbackConstants;
|
||||||
|
|
||||||
class Vibration {
|
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
|
||||||
static int getNoVibration() {
|
import io.github.sspanak.tt9.ui.main.keys.SoftNumberKey;
|
||||||
|
|
||||||
|
public class Vibration {
|
||||||
|
public static int getNoVibration() {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getPressVibration(SoftKey key) {
|
public static int getPressVibration(SoftKey key) {
|
||||||
return key instanceof SoftNumberKey ? HapticFeedbackConstants.KEYBOARD_TAP : HapticFeedbackConstants.VIRTUAL_KEY;
|
return key instanceof SoftNumberKey ? HapticFeedbackConstants.KEYBOARD_TAP : HapticFeedbackConstants.VIRTUAL_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getHoldVibration() {
|
public static int getHoldVibration() {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
return HapticFeedbackConstants.CONFIRM;
|
return HapticFeedbackConstants.CONFIRM;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -20,8 +23,7 @@ class Vibration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int getReleaseVibration() {
|
||||||
static int getReleaseVibration() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
||||||
return HapticFeedbackConstants.KEYBOARD_RELEASE;
|
return HapticFeedbackConstants.KEYBOARD_RELEASE;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
package io.github.sspanak.tt9.ui.main.keys;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.R;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
|
|
||||||
|
public class ResizeHandle implements View.OnTouchListener {
|
||||||
|
@NonNull private final Runnable onClick;
|
||||||
|
private ResizableMainView mainView;
|
||||||
|
|
||||||
|
private final float RESIZE_THRESHOLD;
|
||||||
|
private boolean dragging;
|
||||||
|
private float startY;
|
||||||
|
|
||||||
|
|
||||||
|
ResizeHandle(@NonNull Context context, @NonNull Runnable onClick) {
|
||||||
|
RESIZE_THRESHOLD = context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 4.0f;
|
||||||
|
this.onClick = onClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMainView(ResizableMainView mainView) {
|
||||||
|
this.mainView = mainView;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
switch(event.getAction() & MotionEvent.ACTION_MASK) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
handlePress(event);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
handleDrag(event);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
handleRelease(event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handlePress(MotionEvent event) {
|
||||||
|
startY = event.getRawY();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleDrag(MotionEvent event) {
|
||||||
|
if (mainView == null) {
|
||||||
|
dragging = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dragging && Math.abs(event.getRawY() - startY) >= RESIZE_THRESHOLD) {
|
||||||
|
mainView.onResizeStart(event.getRawY());
|
||||||
|
dragging = true;
|
||||||
|
} else if (dragging) {
|
||||||
|
mainView.onResizeThrottled(event.getRawY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRelease(MotionEvent event) {
|
||||||
|
if (mainView != null && dragging) {
|
||||||
|
mainView.onResize(event.getRawY());
|
||||||
|
dragging = false;
|
||||||
|
} else {
|
||||||
|
onClick.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import android.view.KeyEvent;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
|
|
||||||
public class SoftBackspaceKey extends SoftKey {
|
public class SoftBackspaceKey extends SoftKey {
|
||||||
private boolean hold;
|
private boolean hold;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
|
|
||||||
public class SoftFilterKey extends SoftKey {
|
public class SoftFilterKey extends SoftKey {
|
||||||
public SoftFilterKey(Context context) { super(context); setFontSize(); }
|
public SoftFilterKey(Context context) { super(context); setFontSize(); }
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
|
|
||||||
public class SoftInputModeKey extends SoftKey {
|
public class SoftInputModeKey extends SoftKey {
|
||||||
public SoftInputModeKey(Context context) {
|
public SoftInputModeKey(Context context) {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import androidx.core.content.ContextCompat;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
import io.github.sspanak.tt9.util.Characters;
|
import io.github.sspanak.tt9.util.Characters;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
|
|
@ -38,16 +39,22 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
public SoftKey(Context context) {
|
public SoftKey(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
setHapticFeedbackEnabled(false);
|
setHapticFeedbackEnabled(false);
|
||||||
|
setOnTouchListener(this);
|
||||||
|
setOnLongClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoftKey(Context context, AttributeSet attrs) {
|
public SoftKey(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
setHapticFeedbackEnabled(false);
|
setHapticFeedbackEnabled(false);
|
||||||
|
setOnTouchListener(this);
|
||||||
|
setOnLongClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SoftKey(Context context, AttributeSet attrs, int defStyleAttr) {
|
public SoftKey(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
setHapticFeedbackEnabled(false);
|
setHapticFeedbackEnabled(false);
|
||||||
|
setOnTouchListener(this);
|
||||||
|
setOnLongClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -66,19 +73,6 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFinishInflate() {
|
|
||||||
super.onFinishInflate();
|
|
||||||
View keyView = findViewById(getId());
|
|
||||||
if (keyView != null) {
|
|
||||||
keyView.setOnTouchListener(this);
|
|
||||||
keyView.setOnLongClickListener(this);
|
|
||||||
} else {
|
|
||||||
Logger.e(LOG_TAG, "Failed settings touch listeners. Cannot find SoftKey with ID: " + getId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View view, MotionEvent event) {
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
super.onTouchEvent(event);
|
super.onTouchEvent(event);
|
||||||
|
|
@ -164,7 +158,6 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
}
|
}
|
||||||
|
|
||||||
int keyId = getId();
|
int keyId = getId();
|
||||||
if (keyId == R.id.soft_key_command_palette) return tt9.onKeyCommandPalette(false);
|
|
||||||
if (keyId == R.id.soft_key_voice_input) { tt9.toggleVoiceInput(); return true; }
|
if (keyId == R.id.soft_key_voice_input) { tt9.toggleVoiceInput(); return true; }
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
|
|
||||||
public class SoftKeyArrow extends SoftKey {
|
public class SoftKeyArrow extends SoftKey {
|
||||||
private boolean hold;
|
private boolean hold;
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,35 @@ package io.github.sspanak.tt9.ui.main.keys;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
|
|
||||||
public class SoftKeyCommandPalette extends SoftKey {
|
public class SoftKeyCommandPalette extends SoftKey {
|
||||||
|
private final ResizeHandle resizeHandle = new ResizeHandle(getContext(), this::showCommandPalette);
|
||||||
|
|
||||||
public SoftKeyCommandPalette(Context context) { super(context); }
|
public SoftKeyCommandPalette(Context context) { super(context); }
|
||||||
public SoftKeyCommandPalette(Context context, AttributeSet attrs) { super(context, attrs); }
|
public SoftKeyCommandPalette(Context context, AttributeSet attrs) { super(context, attrs); }
|
||||||
public SoftKeyCommandPalette(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
|
public SoftKeyCommandPalette(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
|
||||||
|
|
||||||
|
public void setMainView(ResizableMainView mainView) {
|
||||||
|
resizeHandle.setMainView(mainView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
|
resizeHandle.onTouch(view, event);
|
||||||
|
return super.onTouch(view, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showCommandPalette() {
|
||||||
|
if (validateTT9Handler()) {
|
||||||
|
tt9.onKeyCommandPalette(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getNoEmojiTitle() {
|
protected int getNoEmojiTitle() {
|
||||||
return R.string.virtual_key_command_palette;
|
return R.string.virtual_key_command_palette;
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,44 @@ package io.github.sspanak.tt9.ui.main.keys;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
|
|
||||||
public class SoftKeySettings extends SoftKey {
|
public class SoftKeySettings extends SoftKey {
|
||||||
public SoftKeySettings(Context context) { super(context); }
|
private final ResizeHandle resizeHandle = new ResizeHandle(getContext(), this::showSettings);
|
||||||
public SoftKeySettings(Context context, AttributeSet attrs) { super(context, attrs); }
|
|
||||||
public SoftKeySettings(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
|
public SoftKeySettings(Context context) {
|
||||||
|
super(context);
|
||||||
|
setOnLongClickListener(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoftKeySettings(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
setOnLongClickListener(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SoftKeySettings(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
setOnLongClickListener(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMainView(ResizableMainView mainView) {
|
||||||
|
resizeHandle.setMainView(mainView);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handleRelease() {
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
|
resizeHandle.onTouch(view, event);
|
||||||
|
return super.onTouch(view, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void showSettings() {
|
||||||
if (validateTT9Handler()) {
|
if (validateTT9Handler()) {
|
||||||
tt9.showSettings();
|
tt9.showSettings();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
import io.github.sspanak.tt9.languages.Language;
|
import io.github.sspanak.tt9.languages.Language;
|
||||||
import io.github.sspanak.tt9.languages.LanguageKind;
|
import io.github.sspanak.tt9.languages.LanguageKind;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.Vibration;
|
||||||
import io.github.sspanak.tt9.util.Logger;
|
import io.github.sspanak.tt9.util.Logger;
|
||||||
|
|
||||||
public class SoftNumberKey extends SoftKey {
|
public class SoftNumberKey extends SoftKey {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.content.Context;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
@ -19,12 +20,15 @@ import java.util.List;
|
||||||
|
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
|
||||||
|
import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
|
|
||||||
public class SuggestionsBar {
|
public class SuggestionsBar {
|
||||||
|
private double lastClickTime = 0;
|
||||||
private final List<String> suggestions = new ArrayList<>();
|
private final List<String> suggestions = new ArrayList<>();
|
||||||
protected int selectedIndex = 0;
|
protected int selectedIndex = 0;
|
||||||
private boolean isDarkThemeEnabled = false;
|
private boolean isDarkThemeEnabled = false;
|
||||||
|
|
||||||
|
private final ResizableMainView mainView;
|
||||||
private final Runnable onItemClick;
|
private final Runnable onItemClick;
|
||||||
private final RecyclerView mView;
|
private final RecyclerView mView;
|
||||||
private final SettingsStore settings;
|
private final SettingsStore settings;
|
||||||
|
|
@ -33,17 +37,23 @@ public class SuggestionsBar {
|
||||||
private final Handler alternativeScrollingHandler = new Handler();
|
private final Handler alternativeScrollingHandler = new Handler();
|
||||||
|
|
||||||
|
|
||||||
public SuggestionsBar(@NonNull SettingsStore settings, @NonNull View mainView, @NonNull Runnable onItemClick) {
|
public SuggestionsBar(@NonNull SettingsStore settings, @NonNull ResizableMainView mainView, @NonNull Runnable onItemClick) {
|
||||||
this.onItemClick = onItemClick;
|
this.onItemClick = onItemClick;
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
|
|
||||||
mView = mainView.findViewById(R.id.suggestions_bar);
|
this.mainView = mainView;
|
||||||
|
mView = mainView.getView() != null ? mainView.getView().findViewById(R.id.suggestions_bar) : null;
|
||||||
if (mView != null) {
|
if (mView != null) {
|
||||||
mView.setLayoutManager(new LinearLayoutManager(mainView.getContext(), RecyclerView.HORIZONTAL, false));
|
Context context = mainView.getView().getContext();
|
||||||
|
|
||||||
initDataAdapter(mainView.getContext());
|
mView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
|
||||||
initSeparator(mainView.getContext());
|
mView.setOnTouchListener(this::onTouch);
|
||||||
|
|
||||||
|
initDataAdapter(context);
|
||||||
|
initSeparator(context);
|
||||||
configureAnimation();
|
configureAnimation();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,4 +261,35 @@ public class SuggestionsBar {
|
||||||
selectedIndex = position;
|
selectedIndex = position;
|
||||||
onItemClick.run();
|
onItemClick.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean onTouch(View view, MotionEvent event) {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int action = event.getAction();
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
mainView.onResizeStart(event.getRawY());
|
||||||
|
return true;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
mainView.onResizeThrottled(event.getRawY());
|
||||||
|
return true;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
if (now - lastClickTime < SettingsStore.SOFT_KEY_DOUBLE_CLICK_DELAY) {
|
||||||
|
mainView.onSnap();
|
||||||
|
} else {
|
||||||
|
mainView.onResize(event.getRawY());
|
||||||
|
}
|
||||||
|
|
||||||
|
lastClickTime = now;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@
|
||||||
<string name="pref_layout_small">Function keys</string>
|
<string name="pref_layout_small">Function keys</string>
|
||||||
<string name="pref_layout_stealth">Invisible</string>
|
<string name="pref_layout_stealth">Invisible</string>
|
||||||
<string name="pref_layout_tray">Suggestion list only</string>
|
<string name="pref_layout_tray">Suggestion list only</string>
|
||||||
|
<string name="pref_numpad_key_height">Virtual Numpad Key Size</string>
|
||||||
<string name="pref_font_size">Settings Font Size</string>
|
<string name="pref_font_size">Settings Font Size</string>
|
||||||
<string name="pref_font_size_default">Default</string>
|
<string name="pref_font_size_default">Default</string>
|
||||||
<string name="pref_font_size_large">Large</string>
|
<string name="pref_font_size_large">Large</string>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@
|
||||||
app:title="@string/pref_haptic_feedback"
|
app:title="@string/pref_haptic_feedback"
|
||||||
app:summary="@string/pref_haptic_feedback_summary"/>
|
app:summary="@string/pref_haptic_feedback_summary"/>
|
||||||
|
|
||||||
|
<DropDownPreference
|
||||||
|
app:key="pref_numpad_key_height"
|
||||||
|
app:title="@string/pref_numpad_key_height" />
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
app:key="pref_status_icon"
|
app:key="pref_status_icon"
|
||||||
app:title="@string/pref_status_icon"
|
app:title="@string/pref_status_icon"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue