1
0
Fork 0

UI resize

This commit is contained in:
Dimo Karaivanov 2024-06-27 16:03:44 +03:00
parent 2bfabd2ec8
commit 867b3be578
31 changed files with 602 additions and 59 deletions

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:tools="http://schemas.android.com/tools"
android:versionCode="573"
android:versionName="34.0"
android:versionCode="580"
android:versionName="34.7"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/> <!-- allows displaying notifications on Android >= 13 -->

View file

@ -1,7 +1,6 @@
package io.github.sspanak.tt9.ime;
import android.inputmethodservice.InputMethodService;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@ -24,7 +23,7 @@ abstract public class AbstractHandler extends InputMethodService {
abstract protected void setInputField(InputConnection inputConnection, EditorInfo inputField);
// UI
abstract protected void createSuggestionBar(View mainView);
abstract protected void createSuggestionBar();
abstract protected void resetStatus();

View file

@ -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.languages.Language;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.main.ResizableMainView;
abstract public class MainViewHandler extends HotkeyHandler {
/**** Informational methods for the on-screen keyboard ****/
@ -46,6 +47,10 @@ abstract public class MainViewHandler extends HotkeyHandler {
return mLanguage;
}
public ResizableMainView getMainView() {
return mainView;
}
public SettingsStore getSettings() {
return settings;
}

View file

@ -1,7 +1,6 @@
package io.github.sspanak.tt9.ime;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@ -42,8 +41,8 @@ public abstract class TypingHandler extends KeyPadHandler {
protected Language mLanguage;
protected void createSuggestionBar(View mainView) {
suggestionOps = new SuggestionOps(settings, mainView, this::onAcceptSuggestionsDelayed, this::onOK);
protected void createSuggestionBar() {
suggestionOps = new SuggestionOps(settings, mainView, textField, this::onAcceptSuggestionsDelayed, this::onOK);
}

View file

@ -7,19 +7,19 @@ import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.hacks.DeviceInfo;
import io.github.sspanak.tt9.ime.modes.InputMode;
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;
abstract class UiHandler extends AbstractHandler {
protected SettingsStore settings;
protected MainView mainView = null;
protected ResizableMainView mainView = null;
protected StatusBar statusBar = null;
@Override
protected void onInit() {
if (mainView == null) {
mainView = new MainView(getFinalContext());
mainView = new ResizableMainView(getFinalContext());
initTray();
}
}
@ -27,12 +27,12 @@ abstract class UiHandler extends AbstractHandler {
protected void initTray() {
setInputView(mainView.getView());
createSuggestionBar(mainView.getView());
createSuggestionBar();
statusBar = new StatusBar(mainView.getView());
}
protected void initUi() {
public void initUi() {
if (mainView.createInputView()) {
initTray();
}

View file

@ -2,13 +2,13 @@ package io.github.sspanak.tt9.ime.helpers;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import androidx.annotation.NonNull;
import java.util.ArrayList;
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.util.ConsumerCompat;
@ -19,12 +19,12 @@ public class SuggestionOps {
@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());
this.onDelayedAccept = onDelayedAccept;
suggestionBar = new SuggestionsBar(settings, mainView, onSuggestionClick);
textField = new TextField(null, null);
this.textField = textField;
}

View file

@ -9,7 +9,7 @@ import java.util.LinkedHashMap;
import io.github.sspanak.tt9.util.Logger;
abstract public class ItemDropDown {
private final DropDownPreference item;
protected final DropDownPreference item;
private LinkedHashMap<String, String> values;
public ItemDropDown(DropDownPreference item) {

View file

@ -26,10 +26,18 @@ public class AppearanceScreen extends BaseScreenFragment {
(new ItemStatusIcon(findPreference(ItemStatusIcon.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 = {
new ItemSelectTheme(findPreference(ItemSelectTheme.NAME), activity),
new ItemSelectLayoutType(findPreference(ItemSelectLayoutType.NAME), activity, hapticFeedback::populate),
new ItemSelectSettingsFontSize(findPreference(ItemSelectSettingsFontSize.NAME), this)
new ItemSelectLayoutType(
findPreference(ItemSelectLayoutType.NAME),
activity,
(layout) -> {
hapticFeedback.onLayoutChange(layout);
numpadKeyHeight.onLayoutChange(layout);
}),
new ItemSelectSettingsFontSize(findPreference(ItemSelectSettingsFontSize.NAME), this),
numpadKeyHeight
};
for (ItemDropDown item : items) {

View file

@ -22,16 +22,14 @@ class ItemHapticFeedback extends ItemClickable {
}
ItemHapticFeedback populate() {
return populate(settings.getMainViewLayout());
onLayoutChange(settings.getMainViewLayout());
return this;
}
ItemHapticFeedback populate(int mainViewLayout) {
void onLayoutChange(int mainViewLayout) {
if (item != null) {
item.setEnabled(mainViewLayout == SettingsStore.LAYOUT_NUMPAD || mainViewLayout == SettingsStore.LAYOUT_SMALL);
((SwitchPreferenceCompat) item).setChecked(settings.getHapticFeedback());
}
return this;
}
}

View file

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

View file

@ -13,7 +13,9 @@ public class SettingsStore extends SettingsUI {
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_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 int SOFT_KEY_DOUBLE_CLICK_DELAY = 500; // ms
public final static int SOFT_KEY_REPEAT_DELAY = 40; // ms
public final static int SOFT_KEY_TITLE_SIZE = 18; // sp
public final static float SOFT_KEY_COMPLEX_LABEL_TITLE_RELATIVE_SIZE = 0.55f;

View file

@ -5,7 +5,9 @@ import android.content.res.Configuration;
import androidx.appcompat.app.AppCompatDelegate;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.hacks.DeviceInfo;
import io.github.sspanak.tt9.util.Logger;
public class SettingsUI extends SettingsTyping {
public final static int FONT_SIZE_DEFAULT = 0;
@ -36,6 +38,14 @@ public class SettingsUI extends SettingsTyping {
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() {
int defaultSize = DeviceInfo.isQinF21() || DeviceInfo.isLgX100S() ? FONT_SIZE_LARGE : FONT_SIZE_DEFAULT;
return getStringifiedInt("pref_font_size", defaultSize);
@ -45,6 +55,16 @@ public class SettingsUI extends SettingsTyping {
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() {
int defaultLayout = LAYOUT_SMALL;
if (DeviceInfo.noTouchScreen(context)) {

View file

@ -77,6 +77,12 @@ abstract class BaseMainLayout {
}
int getHeight() {
return 0;
}
void resetHeight() {}
/**
* render
* Do all the necessary stuff to display the View.

View file

@ -1,5 +1,6 @@
package io.github.sspanak.tt9.ui.main;
import android.content.res.Resources;
import android.view.View;
import android.view.ViewGroup;
@ -12,8 +13,12 @@ import java.util.Arrays;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
import io.github.sspanak.tt9.ui.main.keys.SoftKeySettings;
class MainLayoutNumpad extends BaseMainLayout {
private int height;
MainLayoutNumpad(TraditionalT9 tt9) {
super(tt9, R.layout.main_numpad);
}
@ -34,6 +39,7 @@ class MainLayoutNumpad extends BaseMainLayout {
);
}
@Override
void setDarkTheme(boolean dark) {
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
void render() {
getView();
setKeyHeight(tt9 != null ? tt9.getSettings().getNumpadKeyHeight() : -1);
enableClickHandlers();
for (SoftKey key : getKeys()) {
key.render();
}
}
@Override
protected void enableClickHandlers() {
super.enableClickHandlers();
for (SoftKey key : getKeys()) {
if (key instanceof SoftKeySettings) {
((SoftKeySettings) key).setMainView(tt9.getMainView());
}
}
}
@NonNull
@Override
protected ArrayList<SoftKey> getKeys() {
@ -89,6 +146,7 @@ class MainLayoutNumpad extends BaseMainLayout {
return keys;
}
protected ArrayList<View> getSeparators() {
// it's fine... it's shorter, faster and easier to read than searching with 3 nested loops
return new ArrayList<>(Arrays.asList(

View file

@ -1,5 +1,6 @@
package io.github.sspanak.tt9.ui.main;
import android.content.res.Resources;
import android.view.View;
import android.widget.LinearLayout;
@ -10,12 +11,25 @@ import java.util.ArrayList;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
import io.github.sspanak.tt9.ui.main.keys.SoftKeyCommandPalette;
class MainLayoutSmall extends MainLayoutTray {
private int height;
MainLayoutSmall(TraditionalT9 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
protected void setSoftKeysVisibility() {
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
@Override
protected ArrayList<SoftKey> getKeys() {

View file

@ -1,5 +1,6 @@
package io.github.sspanak.tt9.ui.main;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.widget.LinearLayout;
@ -15,10 +16,20 @@ import io.github.sspanak.tt9.ime.TraditionalT9;
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
class MainLayoutTray extends BaseMainLayout {
private int height;
MainLayoutTray(TraditionalT9 tt9) {
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() {
if (view != null) {
view.findViewById(R.id.main_soft_keys).setVisibility(LinearLayout.GONE);

View file

@ -7,10 +7,11 @@ import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.util.Logger;
public class MainView {
private final TraditionalT9 tt9;
private BaseMainLayout main;
protected final TraditionalT9 tt9;
protected BaseMainLayout main;
public MainView(TraditionalT9 tt9) {
protected MainView(TraditionalT9 tt9) {
this.tt9 = tt9;
forceCreateInputView();
@ -32,6 +33,7 @@ public class MainView {
}
main.render();
return true;
}

View file

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

View file

@ -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.view.HapticFeedbackConstants;
class Vibration {
static int getNoVibration() {
import io.github.sspanak.tt9.ui.main.keys.SoftKey;
import io.github.sspanak.tt9.ui.main.keys.SoftNumberKey;
public class Vibration {
public static int getNoVibration() {
return -1;
}
static int getPressVibration(SoftKey key) {
public static int getPressVibration(SoftKey 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) {
return HapticFeedbackConstants.CONFIRM;
} else {
@ -20,8 +23,7 @@ class Vibration {
}
}
static int getReleaseVibration() {
public static int getReleaseVibration() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
return HapticFeedbackConstants.KEYBOARD_RELEASE;
} else {

View file

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

View file

@ -6,6 +6,7 @@ import android.view.KeyEvent;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.languages.LanguageKind;
import io.github.sspanak.tt9.ui.main.Vibration;
public class SoftBackspaceKey extends SoftKey {
private boolean hold;

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.util.AttributeSet;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.main.Vibration;
public class SoftFilterKey extends SoftKey {
public SoftFilterKey(Context context) { super(context); setFontSize(); }

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.util.AttributeSet;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ui.main.Vibration;
public class SoftInputModeKey extends SoftKey {
public SoftInputModeKey(Context context) {

View file

@ -18,6 +18,7 @@ import androidx.core.content.ContextCompat;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ime.TraditionalT9;
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.Logger;
@ -38,16 +39,22 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
public SoftKey(Context context) {
super(context);
setHapticFeedbackEnabled(false);
setOnTouchListener(this);
setOnLongClickListener(this);
}
public SoftKey(Context context, AttributeSet attrs) {
super(context, attrs);
setHapticFeedbackEnabled(false);
setOnTouchListener(this);
setOnLongClickListener(this);
}
public SoftKey(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
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
public boolean onTouch(View view, MotionEvent event) {
super.onTouchEvent(event);
@ -164,7 +158,6 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
}
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; }
return false;

View file

@ -4,6 +4,7 @@ import android.content.Context;
import android.util.AttributeSet;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ui.main.Vibration;
public class SoftKeyArrow extends SoftKey {
private boolean hold;

View file

@ -2,14 +2,35 @@ package io.github.sspanak.tt9.ui.main.keys;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ui.main.ResizableMainView;
public class SoftKeyCommandPalette extends SoftKey {
private final ResizeHandle resizeHandle = new ResizeHandle(getContext(), this::showCommandPalette);
public SoftKeyCommandPalette(Context context) { super(context); }
public SoftKeyCommandPalette(Context context, AttributeSet attrs) { super(context, attrs); }
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
protected int getNoEmojiTitle() {
return R.string.virtual_key_command_palette;

View file

@ -2,22 +2,44 @@ package io.github.sspanak.tt9.ui.main.keys;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.ui.main.ResizableMainView;
public class SoftKeySettings extends SoftKey {
public SoftKeySettings(Context context) { super(context); }
public SoftKeySettings(Context context, AttributeSet attrs) { super(context, attrs); }
public SoftKeySettings(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }
private final ResizeHandle resizeHandle = new ResizeHandle(getContext(), this::showSettings);
@Override
protected boolean handleRelease() {
if (validateTT9Handler()) {
tt9.showSettings();
return true;
public SoftKeySettings(Context context) {
super(context);
setOnLongClickListener(null);
}
return false;
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
public boolean onTouch(View view, MotionEvent event) {
resizeHandle.onTouch(view, event);
return super.onTouch(view, event);
}
protected void showSettings() {
if (validateTT9Handler()) {
tt9.showSettings();
}
}
@Override

View file

@ -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.LanguageKind;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.main.Vibration;
import io.github.sspanak.tt9.util.Logger;
public class SoftNumberKey extends SoftKey {

View file

@ -5,6 +5,7 @@ import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
@ -19,12 +20,15 @@ import java.util.List;
import io.github.sspanak.tt9.R;
import io.github.sspanak.tt9.preferences.settings.SettingsStore;
import io.github.sspanak.tt9.ui.main.ResizableMainView;
public class SuggestionsBar {
private double lastClickTime = 0;
private final List<String> suggestions = new ArrayList<>();
protected int selectedIndex = 0;
private boolean isDarkThemeEnabled = false;
private final ResizableMainView mainView;
private final Runnable onItemClick;
private final RecyclerView mView;
private final SettingsStore settings;
@ -33,17 +37,23 @@ public class SuggestionsBar {
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.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) {
mView.setLayoutManager(new LinearLayoutManager(mainView.getContext(), RecyclerView.HORIZONTAL, false));
Context context = mainView.getView().getContext();
initDataAdapter(mainView.getContext());
initSeparator(mainView.getContext());
mView.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
mView.setOnTouchListener(this::onTouch);
initDataAdapter(context);
initSeparator(context);
configureAnimation();
}
}
@ -251,4 +261,35 @@ public class SuggestionsBar {
selectedIndex = position;
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;
}
}

View file

@ -72,6 +72,7 @@
<string name="pref_layout_small">Function keys</string>
<string name="pref_layout_stealth">Invisible</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_default">Default</string>
<string name="pref_font_size_large">Large</string>

View file

@ -15,6 +15,10 @@
app:title="@string/pref_haptic_feedback"
app:summary="@string/pref_haptic_feedback_summary"/>
<DropDownPreference
app:key="pref_numpad_key_height"
app:title="@string/pref_numpad_key_height" />
<SwitchPreferenceCompat
app:key="pref_status_icon"
app:title="@string/pref_status_icon"