Fixed on-screen keys holding
* Backspace works properly * holding 0-key now types '+' in 123 mode * holding the punctuation keys now allows for typing ',' and '.' in 123 mode
This commit is contained in:
parent
6173291a1c
commit
b8b05c6d1b
4 changed files with 184 additions and 97 deletions
|
|
@ -2,15 +2,10 @@ 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.Logger;
|
||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
||||
|
||||
public class SoftBackspaceKey extends SoftKey {
|
||||
private SettingsStore settings;
|
||||
long lastBackspaceCall = 0;
|
||||
|
||||
public SoftBackspaceKey(Context context) {
|
||||
super(context);
|
||||
|
|
@ -24,52 +19,23 @@ public class SoftBackspaceKey extends SoftKey {
|
|||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
private SettingsStore getSettings() {
|
||||
if (settings == null) {
|
||||
settings = new SettingsStore(getContext());
|
||||
}
|
||||
|
||||
return settings;
|
||||
@Override
|
||||
final protected boolean handlePress() {
|
||||
return handleHold();
|
||||
}
|
||||
|
||||
@Override
|
||||
final public boolean onTouch(View view, MotionEvent event) {
|
||||
final protected boolean handleHold() {
|
||||
if (tt9 == null) {
|
||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int action = event.getAction() & MotionEvent.ACTION_MASK;
|
||||
|
||||
if (action == MotionEvent.AXIS_PRESSURE) {
|
||||
handleHold();
|
||||
} else if (action == MotionEvent.ACTION_UP) {
|
||||
handleUp();
|
||||
} else if (action == MotionEvent.ACTION_DOWN) {
|
||||
// Fallback for phones that do not report AXIS_PRESSURE, when a key is being held
|
||||
handlePress(-1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void handleHold() {
|
||||
if (System.currentTimeMillis() - lastBackspaceCall < getSettings().getSoftKeyRepeatDelay()) {
|
||||
return;
|
||||
}
|
||||
|
||||
handlePress(-1);
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
lastBackspaceCall = lastBackspaceCall == 0 ? getSettings().getSoftKeyInitialDelay() + now : now;
|
||||
}
|
||||
|
||||
private void handleUp() {
|
||||
lastBackspaceCall = 0;
|
||||
return tt9.onBackspace();
|
||||
}
|
||||
|
||||
@Override
|
||||
final protected boolean handlePress(int b) {
|
||||
return tt9.onBackspace();
|
||||
final protected boolean handleRelease() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package io.github.sspanak.tt9.ui.main.keys;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
|
|
@ -16,11 +18,17 @@ import io.github.sspanak.tt9.Logger;
|
|||
import io.github.sspanak.tt9.R;
|
||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
||||
|
||||
public class SoftKey extends androidx.appcompat.widget.AppCompatButton implements View.OnTouchListener {
|
||||
public class SoftKey extends androidx.appcompat.widget.AppCompatButton implements View.OnTouchListener, View.OnLongClickListener {
|
||||
protected TraditionalT9 tt9;
|
||||
|
||||
protected float COMPLEX_LABEL_TITLE_SIZE = 0.55f;
|
||||
protected float COMPLEX_LABEL_SUB_TITLE_SIZE = 0.8f;
|
||||
|
||||
private boolean hold = false;
|
||||
private boolean repeat = false;
|
||||
private final Handler repeatHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
|
||||
public SoftKey(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
|
@ -33,6 +41,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
|
||||
public void setTT9(TraditionalT9 tt9) {
|
||||
this.tt9 = tt9;
|
||||
}
|
||||
|
|
@ -50,25 +59,82 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
getRootView().setOnTouchListener(this);
|
||||
getRootView().setOnLongClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
super.onTouchEvent(event);
|
||||
|
||||
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
||||
return handlePress(view.getId());
|
||||
int action = (event.getAction() & MotionEvent.ACTION_MASK);
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
return handlePress();
|
||||
} else if (action == MotionEvent.ACTION_UP) {
|
||||
preventRepeat();
|
||||
if (!repeat) {
|
||||
return handleRelease();
|
||||
}
|
||||
repeat = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handlePress(int keyId) {
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
hold = true;
|
||||
|
||||
// sometimes this gets called twice, so we debounce the call to the repeating function
|
||||
repeatHandler.removeCallbacks(this::repeatOnLongPress);
|
||||
repeatHandler.postDelayed(this::repeatOnLongPress, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* repeatOnLongPress
|
||||
* Repeatedly calls "handleHold()" upon holding the respective SoftKey, to simulate physical keyboard behavior.
|
||||
*/
|
||||
private void repeatOnLongPress() {
|
||||
if (tt9 == null) {
|
||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||
hold = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (hold) {
|
||||
repeat = true;
|
||||
handleHold();
|
||||
repeatHandler.removeCallbacks(this::repeatOnLongPress);
|
||||
repeatHandler.postDelayed(this::repeatOnLongPress, tt9.getSettings().getSoftKeyRepeatDelay());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* preventRepeat
|
||||
* Prevents "handleHold()" from being called repeatedly when the SoftKey is being held.
|
||||
*/
|
||||
protected void preventRepeat() {
|
||||
hold = false;
|
||||
repeatHandler.removeCallbacks(this::repeatOnLongPress);
|
||||
}
|
||||
|
||||
protected boolean handlePress() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleHold() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean handleRelease() {
|
||||
if (tt9 == null) {
|
||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyId = getId();
|
||||
|
||||
if (keyId == R.id.soft_key_add_word) return tt9.onKeyAddWord();
|
||||
if (keyId == R.id.soft_key_input_mode) return tt9.onKeyNextInputMode();
|
||||
if (keyId == R.id.soft_key_language) return tt9.onKeyNextLanguage();
|
||||
|
|
@ -99,7 +165,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
|
||||
/**
|
||||
* render
|
||||
* Sets the key label using "getKeyNameLabel()" and "getKeyFunctionLabel()" or if they both
|
||||
* Sets the key label using "getTitle()" and "getSubtitle()" or if they both
|
||||
* return NULL, the XML "text" attribute will be preserved.
|
||||
*
|
||||
* If there is only name label, it will be centered and at normal font size.
|
||||
|
|
@ -107,19 +173,19 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
|||
* have their font size adjusted to fit inside the key.
|
||||
*/
|
||||
public void render() {
|
||||
String name = getTitle();
|
||||
String func = getSubTitle();
|
||||
String title = getTitle();
|
||||
String subtitle = getSubTitle();
|
||||
|
||||
if (name == null) {
|
||||
if (title == null) {
|
||||
return;
|
||||
} else if (func == null) {
|
||||
setText(name);
|
||||
} else if (subtitle == null) {
|
||||
setText(title);
|
||||
return;
|
||||
}
|
||||
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder(name);
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder(title);
|
||||
sb.append('\n');
|
||||
sb.append(func);
|
||||
sb.append(subtitle);
|
||||
|
||||
sb.setSpan(new RelativeSizeSpan(COMPLEX_LABEL_TITLE_SIZE), 0, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||
sb.setSpan(new StyleSpan(Typeface.ITALIC), 0, 2, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
|
||||
|
|
|
|||
|
|
@ -26,13 +26,26 @@ public class SoftNumberKey extends SoftKey {
|
|||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
protected boolean handlePress(int keyId) {
|
||||
@Override
|
||||
protected boolean handleHold() {
|
||||
if (tt9 == null || tt9.getSettings().getInputMode() != InputMode.MODE_123 || getId() != R.id.soft_key_0) {
|
||||
return super.handleHold();
|
||||
}
|
||||
|
||||
preventRepeat();
|
||||
int zeroCode = Key.numberToCode(0);
|
||||
tt9.onKeyLongPress(zeroCode, new KeyEvent(KeyEvent.ACTION_DOWN, zeroCode));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleRelease() {
|
||||
if (tt9 == null) {
|
||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyCode = Key.numberToCode(getNumber(keyId));
|
||||
int keyCode = Key.numberToCode(getNumber(getId()));
|
||||
if (keyCode < 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -43,6 +56,58 @@ public class SoftNumberKey extends SoftKey {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return String.valueOf(getNumber(getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
if (tt9 == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int number = getNumber(getId());
|
||||
|
||||
if (number == 0) {
|
||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
return "+";
|
||||
} else {
|
||||
COMPLEX_LABEL_SUB_TITLE_SIZE = 1;
|
||||
return "␣";
|
||||
}
|
||||
}
|
||||
|
||||
// no special labels in 123 mode
|
||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1
|
||||
if (number == 1) {
|
||||
return ",:-)";
|
||||
}
|
||||
|
||||
// 2-9
|
||||
int textCase = tt9.getSettings().getTextCase();
|
||||
Language language = LanguageCollection.getLanguage(tt9.getSettings().getInputLanguage());
|
||||
|
||||
if (language == null) {
|
||||
Logger.d("SoftNumberKey.getLabel", "Cannot generate a label when the language is NULL.");
|
||||
return "";
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ArrayList<String> chars = language.getKeyCharacters(number, false);
|
||||
for (int i = 0; i < 5 && i < chars.size(); i++) {
|
||||
sb.append(
|
||||
textCase == InputMode.CASE_UPPER ? chars.get(i).toUpperCase(language.getLocale()) : chars.get(i)
|
||||
);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private int getNumber(int keyId) {
|
||||
if (keyId == R.id.soft_key_0) return 0;
|
||||
if (keyId == R.id.soft_key_1) return 1;
|
||||
|
|
@ -57,44 +122,4 @@ public class SoftNumberKey extends SoftKey {
|
|||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
return String.valueOf(getNumber(getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
if (tt9 == null || tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int number = getNumber(getId());
|
||||
int textCase = tt9.getSettings().getTextCase();
|
||||
Language language = LanguageCollection.getLanguage(tt9.getSettings().getInputLanguage());
|
||||
|
||||
if (language == null) {
|
||||
Logger.d("SoftNumberKey.getLabel", "Cannot generate a label when the language is NULL.");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (number == 0) {
|
||||
COMPLEX_LABEL_SUB_TITLE_SIZE = 1;
|
||||
return "␣";
|
||||
}
|
||||
|
||||
if (number == 1) {
|
||||
return ",:-)";
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
ArrayList<String> chars = language.getKeyCharacters(number, false);
|
||||
for (int i = 0; i < 5 && i < chars.size(); i++) {
|
||||
sb.append(
|
||||
textCase == InputMode.CASE_UPPER ? chars.get(i).toUpperCase(language.getLocale()) : chars.get(i)
|
||||
);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,28 @@ public class SoftPunctuationKey extends SoftKey {
|
|||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
protected boolean handlePress(int keyId) {
|
||||
@Override
|
||||
protected boolean handleHold() {
|
||||
if (tt9 == null || tt9.getSettings().getInputMode() != InputMode.MODE_123) {
|
||||
return super.handleHold();
|
||||
}
|
||||
|
||||
preventRepeat();
|
||||
int keyId = getId();
|
||||
if (keyId == R.id.soft_key_punctuation_1) return tt9.onText(",");
|
||||
if (keyId == R.id.soft_key_punctuation_2) return tt9.onText(".");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleRelease() {
|
||||
if (tt9 == null) {
|
||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||
return false;
|
||||
}
|
||||
|
||||
int keyId = getId();
|
||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
if (keyId == R.id.soft_key_punctuation_1) return tt9.onOtherKey(KeyEvent.KEYCODE_STAR);
|
||||
if (keyId == R.id.soft_key_punctuation_2) return tt9.onOtherKey(KeyEvent.KEYCODE_POUND);
|
||||
|
|
@ -40,8 +56,11 @@ public class SoftPunctuationKey extends SoftKey {
|
|||
|
||||
@Override
|
||||
protected String getTitle() {
|
||||
int keyId = getId();
|
||||
if (tt9 == null) {
|
||||
return "PUNC";
|
||||
}
|
||||
|
||||
int keyId = getId();
|
||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
if (keyId == R.id.soft_key_punctuation_1) return "✱";
|
||||
if (keyId == R.id.soft_key_punctuation_2) return "#";
|
||||
|
|
@ -52,4 +71,15 @@ public class SoftPunctuationKey extends SoftKey {
|
|||
|
||||
return "PUNC";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSubTitle() {
|
||||
int keyId = getId();
|
||||
if (tt9 != null && tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||
if (keyId == R.id.soft_key_punctuation_1) return ",";
|
||||
if (keyId == R.id.soft_key_punctuation_2) return ".";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue