From 2369da045fbffa97018f99d073d9e1fe3d14100f Mon Sep 17 00:00:00 2001 From: sspanak Date: Sat, 30 Nov 2024 19:09:26 +0200 Subject: [PATCH] improved the detection of horizontal swiping on the virtual keys, to reduce the accidental swipes when only pressing the key --- .../sspanak/tt9/ime/MainViewHandler.java | 18 ++++++- .../preferences/settings/SettingsStore.java | 1 + .../tt9/ui/main/keys/SoftKeyBackspace.java | 6 +-- .../sspanak/tt9/ui/main/keys/SoftKeyLF4.java | 4 -- .../tt9/ui/main/keys/SoftKeySettings.java | 4 +- .../tt9/ui/main/keys/SwipeableKey.java | 51 +++++++++++++++---- 6 files changed, 65 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java b/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java index f9ae508b..95ff4fc7 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java +++ b/app/src/main/java/io/github/sspanak/tt9/ime/MainViewHandler.java @@ -14,6 +14,7 @@ import io.github.sspanak.tt9.ui.main.ResizableMainView; * Informational methods for the on-screen keyboard **/ abstract public class MainViewHandler extends HotkeyHandler { + private int width = 0; OrientationListener orientationListener; @Override @@ -21,11 +22,18 @@ abstract public class MainViewHandler extends HotkeyHandler { super.onInit(); if (orientationListener == null) { - orientationListener = new OrientationListener(this, mainView::onOrientationChanged); + orientationListener = new OrientationListener(this, this::onOrientationChanged); orientationListener.start(); } } + private void onOrientationChanged() { + width = 0; + if (mainView != null) { + mainView.onOrientationChanged(); + } + } + protected void cleanUp() { if (mainView != null) { mainView.removeListeners(); @@ -107,4 +115,12 @@ abstract public class MainViewHandler extends HotkeyHandler { public SettingsStore getSettings() { return settings; } + + public int getWidth() { + if (width == 0 && mainView != null && mainView.getView() != null) { + width = mainView.getView().getWidth(); + } + + return width; + } } diff --git a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java index dcecfe42..e2d5f264 100644 --- a/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java +++ b/app/src/main/java/io/github/sspanak/tt9/preferences/settings/SettingsStore.java @@ -21,6 +21,7 @@ public class SettingsStore extends SettingsUI { public final static int RESIZE_THROTTLING_TIME = 60; // ms public final static byte SLOW_QUERY_TIME = 50; // ms public final static int SLOW_QUERY_TIMEOUT = 3000; // ms + public final static float SOFT_KEY_AMOUNT_OF_KEY_WIDTH_FOR_SWIPE = 0.75f; // amount of key width 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_MAX_CHARS = 5; diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyBackspace.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyBackspace.java index 34ecc504..a407fa37 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyBackspace.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyBackspace.java @@ -41,8 +41,8 @@ public class SoftKeyBackspace extends SwipeableKey { * moves their finger slightly and the key does not delete anything. */ @Override - protected float getSwipeXThreshold(Context context) { - return isFastDeleteOn() ? super.getSwipeXThreshold(context) : Integer.MAX_VALUE; + protected float getSwipeXThreshold() { + return isFastDeleteOn() ? super.getSwipeXThreshold() : Integer.MAX_VALUE; } @@ -50,7 +50,7 @@ public class SoftKeyBackspace extends SwipeableKey { * Disable vertical swiping for backspace key. */ @Override - protected float getSwipeYThreshold(Context context) { + protected float getSwipeYThreshold() { return Integer.MAX_VALUE; } diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java index 53273b60..93004ed9 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeyLF4.java @@ -18,10 +18,6 @@ public class SoftKeyLF4 extends SwipeableKey { return tt9 != null && tt9.getSettings().getEnabledLanguageIds().size() > 1; } - @Override - protected float getSwipeXThreshold(Context context) { - return super.getSwipeXThreshold(context) * 3; - } @Override protected void handleHold() { diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeySettings.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeySettings.java index f3fcf37a..1803d5f4 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeySettings.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SoftKeySettings.java @@ -25,8 +25,8 @@ public class SoftKeySettings extends SwipeableKey { // this key does not support holding at the moment, so just prevent it @Override protected float getHoldDurationThreshold() { return 1000; } - @Override protected float getSwipeXThreshold(Context context) { return context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height) * 0.75f; } - @Override protected float getSwipeYThreshold(Context context) { return context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 4.0f; } + @Override protected float getSwipeXThreshold() { return getResources().getDimensionPixelSize(R.dimen.numpad_key_height) * 0.75f; } + @Override protected float getSwipeYThreshold() { return getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 4.0f; } @Override protected boolean handleRelease() { diff --git a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SwipeableKey.java b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SwipeableKey.java index 5a5819fc..8236cdcf 100644 --- a/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SwipeableKey.java +++ b/app/src/main/java/io/github/sspanak/tt9/ui/main/keys/SwipeableKey.java @@ -2,11 +2,13 @@ package io.github.sspanak.tt9.ui.main.keys; import android.content.Context; import android.util.AttributeSet; +import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import io.github.sspanak.tt9.R; import io.github.sspanak.tt9.preferences.settings.SettingsStore; +import io.github.sspanak.tt9.util.Logger; import io.github.sspanak.tt9.util.Timer; abstract public class SwipeableKey extends SoftKey { @@ -32,32 +34,62 @@ abstract public class SwipeableKey extends SoftKey { public SwipeableKey(Context context) { super(context); - resetTimeThresholds(context); } public SwipeableKey(Context context, AttributeSet attrs) { super(context, attrs); - resetTimeThresholds(context); } public SwipeableKey(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); - resetTimeThresholds(context); } - protected final void resetTimeThresholds(Context context) { + private void resetTimeThreshold() { HOLD_DURATION_THRESHOLD = getHoldDurationThreshold(); - SWIPE_X_THRESHOLD = getSwipeXThreshold(context); - SWIPE_Y_THRESHOLD = getSwipeYThreshold(context); + } + + + private void initSwipeThresholds() { + if (SWIPE_X_THRESHOLD == 0) { + SWIPE_X_THRESHOLD = getSwipeXThreshold(); + } + + if (SWIPE_Y_THRESHOLD == 0) { + SWIPE_Y_THRESHOLD = getSwipeYThreshold(); + } } protected float getHoldDurationThreshold() { return SettingsStore.SOFT_KEY_REPEAT_DELAY * 9; } - protected float getSwipeXThreshold(Context context) { return context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 10.0f; } - protected float getSwipeYThreshold(Context context) { return context.getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 10.0f; } + protected float getSwipeYThreshold() { return getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 10.0f; } + + + /** + * Calculate the minimum amount of finger movement to be considered a swipe. It is meant + * to prevent accidental swipes when pressing or holding the key. + */ + protected float getSwipeXThreshold() { + // If the key width is not available, use the old method. It's better than nothing. + if (tt9 == null || tt9.getWidth() == 0) { + return getSwipeYThreshold(); + } + + try { + // The simpler getResource.getFloat() requires API 29, so we must get the value manually. + TypedValue outValue = new TypedValue(); + getResources().getValue(R.dimen.numpad_function_key_layout_weight, outValue, true); + float functionKeyScale = outValue.getFloat(); + + float keyWidth = tt9.getWidth() / 5f * functionKeyScale; + return keyWidth * SettingsStore.SOFT_KEY_AMOUNT_OF_KEY_WIDTH_FOR_SWIPE; + } catch (Exception e) { + Logger.e(LOG_TAG, "Error calculating the swipe X threshold. Using default to prevent crashing. " + e); + return getSwipeYThreshold(); + } + } private void updateSwipeTimingStats() { @@ -85,6 +117,7 @@ abstract public class SwipeableKey extends SoftKey { switch(event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: Timer.start(LOG_TAG); + initSwipeThresholds(); onPress(event); break; case MotionEvent.ACTION_MOVE: @@ -172,7 +205,7 @@ abstract public class SwipeableKey extends SoftKey { @Override public void render() { // readjust the action detection delays for keys that set them dynamically - resetTimeThresholds(getContext()); + resetTimeThreshold(); super.render(); } }