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.content.Context;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
import io.github.sspanak.tt9.preferences.SettingsStore;
|
|
||||||
|
|
||||||
public class SoftBackspaceKey extends SoftKey {
|
public class SoftBackspaceKey extends SoftKey {
|
||||||
private SettingsStore settings;
|
|
||||||
long lastBackspaceCall = 0;
|
|
||||||
|
|
||||||
public SoftBackspaceKey(Context context) {
|
public SoftBackspaceKey(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
|
@ -24,52 +19,23 @@ public class SoftBackspaceKey extends SoftKey {
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SettingsStore getSettings() {
|
@Override
|
||||||
if (settings == null) {
|
final protected boolean handlePress() {
|
||||||
settings = new SettingsStore(getContext());
|
return handleHold();
|
||||||
}
|
|
||||||
|
|
||||||
return settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
final public boolean onTouch(View view, MotionEvent event) {
|
final protected boolean handleHold() {
|
||||||
if (tt9 == null) {
|
if (tt9 == null) {
|
||||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int action = event.getAction() & MotionEvent.ACTION_MASK;
|
return tt9.onBackspace();
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
final protected boolean handlePress(int b) {
|
final protected boolean handleRelease() {
|
||||||
return tt9.onBackspace();
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package io.github.sspanak.tt9.ui.main.keys;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.text.SpannableStringBuilder;
|
import android.text.SpannableStringBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.text.style.RelativeSizeSpan;
|
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.R;
|
||||||
import io.github.sspanak.tt9.ime.TraditionalT9;
|
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 TraditionalT9 tt9;
|
||||||
|
|
||||||
protected float COMPLEX_LABEL_TITLE_SIZE = 0.55f;
|
protected float COMPLEX_LABEL_TITLE_SIZE = 0.55f;
|
||||||
protected float COMPLEX_LABEL_SUB_TITLE_SIZE = 0.8f;
|
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) {
|
public SoftKey(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +41,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
super(context, attrs, defStyleAttr);
|
super(context, attrs, defStyleAttr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setTT9(TraditionalT9 tt9) {
|
public void setTT9(TraditionalT9 tt9) {
|
||||||
this.tt9 = tt9;
|
this.tt9 = tt9;
|
||||||
}
|
}
|
||||||
|
|
@ -50,25 +59,82 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
getRootView().setOnTouchListener(this);
|
getRootView().setOnTouchListener(this);
|
||||||
|
getRootView().setOnLongClickListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View view, MotionEvent event) {
|
public boolean onTouch(View view, MotionEvent event) {
|
||||||
super.onTouchEvent(event);
|
super.onTouchEvent(event);
|
||||||
|
|
||||||
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) {
|
int action = (event.getAction() & MotionEvent.ACTION_MASK);
|
||||||
return handlePress(view.getId());
|
|
||||||
|
if (action == MotionEvent.ACTION_DOWN) {
|
||||||
|
return handlePress();
|
||||||
|
} else if (action == MotionEvent.ACTION_UP) {
|
||||||
|
preventRepeat();
|
||||||
|
if (!repeat) {
|
||||||
|
return handleRelease();
|
||||||
|
}
|
||||||
|
repeat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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) {
|
if (tt9 == null) {
|
||||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int keyId = getId();
|
||||||
|
|
||||||
if (keyId == R.id.soft_key_add_word) return tt9.onKeyAddWord();
|
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_input_mode) return tt9.onKeyNextInputMode();
|
||||||
if (keyId == R.id.soft_key_language) return tt9.onKeyNextLanguage();
|
if (keyId == R.id.soft_key_language) return tt9.onKeyNextLanguage();
|
||||||
|
|
@ -99,7 +165,7 @@ public class SoftKey extends androidx.appcompat.widget.AppCompatButton implement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* render
|
* 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.
|
* return NULL, the XML "text" attribute will be preserved.
|
||||||
*
|
*
|
||||||
* If there is only name label, it will be centered and at normal font size.
|
* 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.
|
* have their font size adjusted to fit inside the key.
|
||||||
*/
|
*/
|
||||||
public void render() {
|
public void render() {
|
||||||
String name = getTitle();
|
String title = getTitle();
|
||||||
String func = getSubTitle();
|
String subtitle = getSubTitle();
|
||||||
|
|
||||||
if (name == null) {
|
if (title == null) {
|
||||||
return;
|
return;
|
||||||
} else if (func == null) {
|
} else if (subtitle == null) {
|
||||||
setText(name);
|
setText(title);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SpannableStringBuilder sb = new SpannableStringBuilder(name);
|
SpannableStringBuilder sb = new SpannableStringBuilder(title);
|
||||||
sb.append('\n');
|
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 RelativeSizeSpan(COMPLEX_LABEL_TITLE_SIZE), 0, 2, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
|
||||||
sb.setSpan(new StyleSpan(Typeface.ITALIC), 0, 2, Spanned.SPAN_EXCLUSIVE_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);
|
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) {
|
if (tt9 == null) {
|
||||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int keyCode = Key.numberToCode(getNumber(keyId));
|
int keyCode = Key.numberToCode(getNumber(getId()));
|
||||||
if (keyCode < 0) {
|
if (keyCode < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -43,6 +56,58 @@ public class SoftNumberKey extends SoftKey {
|
||||||
return true;
|
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) {
|
private int getNumber(int keyId) {
|
||||||
if (keyId == R.id.soft_key_0) return 0;
|
if (keyId == R.id.soft_key_0) return 0;
|
||||||
if (keyId == R.id.soft_key_1) return 1;
|
if (keyId == R.id.soft_key_1) return 1;
|
||||||
|
|
@ -57,44 +122,4 @@ public class SoftNumberKey extends SoftKey {
|
||||||
|
|
||||||
return -1;
|
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);
|
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) {
|
if (tt9 == null) {
|
||||||
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
Logger.w(getClass().getCanonicalName(), "Traditional T9 handler is not set. Ignoring key press.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int keyId = getId();
|
||||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
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_1) return tt9.onOtherKey(KeyEvent.KEYCODE_STAR);
|
||||||
if (keyId == R.id.soft_key_punctuation_2) return tt9.onOtherKey(KeyEvent.KEYCODE_POUND);
|
if (keyId == R.id.soft_key_punctuation_2) return tt9.onOtherKey(KeyEvent.KEYCODE_POUND);
|
||||||
|
|
@ -40,8 +56,11 @@ public class SoftPunctuationKey extends SoftKey {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getTitle() {
|
protected String getTitle() {
|
||||||
int keyId = getId();
|
if (tt9 == null) {
|
||||||
|
return "PUNC";
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyId = getId();
|
||||||
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
if (tt9.getSettings().getInputMode() == InputMode.MODE_123) {
|
||||||
if (keyId == R.id.soft_key_punctuation_1) return "✱";
|
if (keyId == R.id.soft_key_punctuation_1) return "✱";
|
||||||
if (keyId == R.id.soft_key_punctuation_2) return "#";
|
if (keyId == R.id.soft_key_punctuation_2) return "#";
|
||||||
|
|
@ -52,4 +71,15 @@ public class SoftPunctuationKey extends SoftKey {
|
||||||
|
|
||||||
return "PUNC";
|
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