improved the detection of horizontal swiping on the virtual keys, to reduce the accidental swipes when only pressing the key
This commit is contained in:
parent
ed651e7ec1
commit
2369da045f
6 changed files with 65 additions and 19 deletions
|
|
@ -14,6 +14,7 @@ import io.github.sspanak.tt9.ui.main.ResizableMainView;
|
||||||
* Informational methods for the on-screen keyboard
|
* Informational methods for the on-screen keyboard
|
||||||
**/
|
**/
|
||||||
abstract public class MainViewHandler extends HotkeyHandler {
|
abstract public class MainViewHandler extends HotkeyHandler {
|
||||||
|
private int width = 0;
|
||||||
OrientationListener orientationListener;
|
OrientationListener orientationListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -21,11 +22,18 @@ abstract public class MainViewHandler extends HotkeyHandler {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
|
||||||
if (orientationListener == null) {
|
if (orientationListener == null) {
|
||||||
orientationListener = new OrientationListener(this, mainView::onOrientationChanged);
|
orientationListener = new OrientationListener(this, this::onOrientationChanged);
|
||||||
orientationListener.start();
|
orientationListener.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onOrientationChanged() {
|
||||||
|
width = 0;
|
||||||
|
if (mainView != null) {
|
||||||
|
mainView.onOrientationChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void cleanUp() {
|
protected void cleanUp() {
|
||||||
if (mainView != null) {
|
if (mainView != null) {
|
||||||
mainView.removeListeners();
|
mainView.removeListeners();
|
||||||
|
|
@ -107,4 +115,12 @@ abstract public class MainViewHandler extends HotkeyHandler {
|
||||||
public SettingsStore getSettings() {
|
public SettingsStore getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
if (width == 0 && mainView != null && mainView.getView() != null) {
|
||||||
|
width = mainView.getView().getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ public class SettingsStore extends SettingsUI {
|
||||||
public final static int RESIZE_THROTTLING_TIME = 60; // 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 SLOW_QUERY_TIMEOUT = 3000; // 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_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_MAX_CHARS = 5;
|
public final static int SOFT_KEY_TITLE_MAX_CHARS = 5;
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ public class SoftKeyBackspace extends SwipeableKey {
|
||||||
* moves their finger slightly and the key does not delete anything.
|
* moves their finger slightly and the key does not delete anything.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected float getSwipeXThreshold(Context context) {
|
protected float getSwipeXThreshold() {
|
||||||
return isFastDeleteOn() ? super.getSwipeXThreshold(context) : Integer.MAX_VALUE;
|
return isFastDeleteOn() ? super.getSwipeXThreshold() : Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ public class SoftKeyBackspace extends SwipeableKey {
|
||||||
* Disable vertical swiping for backspace key.
|
* Disable vertical swiping for backspace key.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected float getSwipeYThreshold(Context context) {
|
protected float getSwipeYThreshold() {
|
||||||
return Integer.MAX_VALUE;
|
return Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,6 @@ public class SoftKeyLF4 extends SwipeableKey {
|
||||||
return tt9 != null && tt9.getSettings().getEnabledLanguageIds().size() > 1;
|
return tt9 != null && tt9.getSettings().getEnabledLanguageIds().size() > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected float getSwipeXThreshold(Context context) {
|
|
||||||
return super.getSwipeXThreshold(context) * 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleHold() {
|
protected void handleHold() {
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ public class SoftKeySettings extends SwipeableKey {
|
||||||
|
|
||||||
// this key does not support holding at the moment, so just prevent it
|
// this key does not support holding at the moment, so just prevent it
|
||||||
@Override protected float getHoldDurationThreshold() { return 1000; }
|
@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 getSwipeXThreshold() { return 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 getSwipeYThreshold() { return getResources().getDimensionPixelSize(R.dimen.numpad_key_height) / 4.0f; }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean handleRelease() {
|
protected boolean handleRelease() {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@ 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.util.TypedValue;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
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.util.Logger;
|
||||||
import io.github.sspanak.tt9.util.Timer;
|
import io.github.sspanak.tt9.util.Timer;
|
||||||
|
|
||||||
abstract public class SwipeableKey extends SoftKey {
|
abstract public class SwipeableKey extends SoftKey {
|
||||||
|
|
@ -32,32 +34,62 @@ abstract public class SwipeableKey extends SoftKey {
|
||||||
|
|
||||||
public SwipeableKey(Context context) {
|
public SwipeableKey(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
resetTimeThresholds(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SwipeableKey(Context context, AttributeSet attrs) {
|
public SwipeableKey(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
resetTimeThresholds(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public SwipeableKey(Context context, AttributeSet attrs, int defStyleAttr) {
|
public SwipeableKey(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
resetTimeThresholds(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected final void resetTimeThresholds(Context context) {
|
private void resetTimeThreshold() {
|
||||||
HOLD_DURATION_THRESHOLD = getHoldDurationThreshold();
|
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 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() { return 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; }
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
private void updateSwipeTimingStats() {
|
||||||
|
|
@ -85,6 +117,7 @@ abstract public class SwipeableKey extends SoftKey {
|
||||||
switch(event.getAction() & MotionEvent.ACTION_MASK) {
|
switch(event.getAction() & MotionEvent.ACTION_MASK) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
case MotionEvent.ACTION_DOWN:
|
||||||
Timer.start(LOG_TAG);
|
Timer.start(LOG_TAG);
|
||||||
|
initSwipeThresholds();
|
||||||
onPress(event);
|
onPress(event);
|
||||||
break;
|
break;
|
||||||
case MotionEvent.ACTION_MOVE:
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
|
@ -172,7 +205,7 @@ abstract public class SwipeableKey extends SoftKey {
|
||||||
@Override
|
@Override
|
||||||
public void render() {
|
public void render() {
|
||||||
// readjust the action detection delays for keys that set them dynamically
|
// readjust the action detection delays for keys that set them dynamically
|
||||||
resetTimeThresholds(getContext());
|
resetTimeThreshold();
|
||||||
super.render();
|
super.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue