1. simplified suggestion scrolling; 2. hopefully fixed the 'spans can not have zero length' warning; 3. fixed repeated words popping over and over again, when scrolling the suggestions in Amazon Kindle app, on the Share Document screen (AppHacks established)
This commit is contained in:
parent
77fd0db39b
commit
e45744e0b4
5 changed files with 77 additions and 24 deletions
|
|
@ -74,8 +74,8 @@ abstract class KeyPadHandler extends InputMethodService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onStartInput(EditorInfo inputField, boolean restarting) {
|
public void onStartInput(EditorInfo inputField, boolean restarting) {
|
||||||
|
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId + " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName + " privateImeOptions: " + inputField.privateImeOptions + " imeOptions: " + inputField.imeOptions + " extras: " + inputField.extras);
|
||||||
currentInputConnection = getCurrentInputConnection();
|
currentInputConnection = getCurrentInputConnection();
|
||||||
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId + " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName);
|
|
||||||
onStart(inputField);
|
onStart(inputField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import java.util.List;
|
||||||
import io.github.sspanak.tt9.Logger;
|
import io.github.sspanak.tt9.Logger;
|
||||||
import io.github.sspanak.tt9.R;
|
import io.github.sspanak.tt9.R;
|
||||||
import io.github.sspanak.tt9.db.DictionaryDb;
|
import io.github.sspanak.tt9.db.DictionaryDb;
|
||||||
|
import io.github.sspanak.tt9.ime.helpers.AppHacks;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
import io.github.sspanak.tt9.ime.helpers.InputModeValidator;
|
||||||
import io.github.sspanak.tt9.ime.helpers.InputType;
|
import io.github.sspanak.tt9.ime.helpers.InputType;
|
||||||
import io.github.sspanak.tt9.ime.helpers.TextField;
|
import io.github.sspanak.tt9.ime.helpers.TextField;
|
||||||
|
|
@ -35,6 +36,7 @@ import io.github.sspanak.tt9.ui.tray.SuggestionsBar;
|
||||||
public class TraditionalT9 extends KeyPadHandler {
|
public class TraditionalT9 extends KeyPadHandler {
|
||||||
// internal settings/data
|
// internal settings/data
|
||||||
private boolean isActive = false;
|
private boolean isActive = false;
|
||||||
|
@NonNull private AppHacks appHacks = new AppHacks(null, null);
|
||||||
@NonNull private TextField textField = new TextField(null, null);
|
@NonNull private TextField textField = new TextField(null, null);
|
||||||
@NonNull private InputType inputType = new InputType(null, null);
|
@NonNull private InputType inputType = new InputType(null, null);
|
||||||
@NonNull private final Handler autoAcceptHandler = new Handler(Looper.getMainLooper());
|
@NonNull private final Handler autoAcceptHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
@ -202,6 +204,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
protected void onStart(EditorInfo input) {
|
protected void onStart(EditorInfo input) {
|
||||||
inputType = new InputType(currentInputConnection, input);
|
inputType = new InputType(currentInputConnection, input);
|
||||||
textField = new TextField(currentInputConnection, input);
|
textField = new TextField(currentInputConnection, input);
|
||||||
|
appHacks = new AppHacks(input, textField);
|
||||||
|
|
||||||
if (!inputType.isValid() || inputType.isLimited()) {
|
if (!inputType.isValid() || inputType.isLimited()) {
|
||||||
// When the input is invalid or simple, let Android handle it.
|
// When the input is invalid or simple, let Android handle it.
|
||||||
|
|
@ -242,6 +245,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
|
|
||||||
public boolean onBackspace() {
|
public boolean onBackspace() {
|
||||||
|
if (appHacks.onBackspace(mInputMode)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// 1. Dialer fields seem to handle backspace on their own and we must ignore it,
|
// 1. Dialer fields seem to handle backspace on their own and we must ignore it,
|
||||||
// otherwise, keyDown race condition occur for all keys.
|
// otherwise, keyDown race condition occur for all keys.
|
||||||
// 2. Allow the assigned key to function normally, when there is no text (e.g. "Back" navigates back)
|
// 2. Allow the assigned key to function normally, when there is no text (e.g. "Back" navigates back)
|
||||||
|
|
@ -296,7 +303,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInputMode.shouldSelectNextSuggestion() && !isSuggestionViewHidden()) {
|
if (mInputMode.shouldSelectNextSuggestion() && !isSuggestionViewHidden()) {
|
||||||
nextSuggestion();
|
onKeyScrollSuggestion(false, false);
|
||||||
scheduleAutoAccept(mInputMode.getAutoAcceptTimeout());
|
scheduleAutoAccept(mInputMode.getAutoAcceptTimeout());
|
||||||
} else {
|
} else {
|
||||||
getSuggestions();
|
getSuggestions();
|
||||||
|
|
@ -311,9 +318,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
if (isSuggestionViewHidden()) {
|
if (isSuggestionViewHidden()) {
|
||||||
return performOKAction();
|
return performOKAction();
|
||||||
} else {
|
|
||||||
acceptCurrentSuggestion(KeyEvent.KEYCODE_ENTER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
acceptCurrentSuggestion(KeyEvent.KEYCODE_ENTER);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,10 +432,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelAutoAccept();
|
cancelAutoAccept();
|
||||||
if (backward) previousSuggestion();
|
suggestionBar.scrollToSuggestion(backward ? -1 : 1);
|
||||||
else nextSuggestion();
|
|
||||||
mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true);
|
mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true);
|
||||||
textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode);
|
setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -493,12 +499,18 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
|
public void onUpdateSelection(int oldSelStart, int oldSelEnd, int newSelStart, int newSelEnd, int candidatesStart, int candidatesEnd) {
|
||||||
|
// Logger.d("onUpdateSelection", "oldSelStart: " + oldSelStart + " oldSelEnd: " + oldSelEnd + " newSelStart: " + newSelStart + " oldSelEnd: " + oldSelEnd + " candidatesStart: " + candidatesStart + " candidatesEnd: " + candidatesEnd);
|
||||||
|
|
||||||
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
|
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
|
||||||
|
|
||||||
// If the cursor moves while composing a word (usually, because the user has touched the screen outside the word), we must
|
// If the cursor moves while composing a word (usually, because the user has touched the screen outside the word), we must
|
||||||
// end typing end accept the word. Otherwise, the cursor would jump back at the end of the word, after the next key press.
|
// end typing end accept the word. Otherwise, the cursor would jump back at the end of the word, after the next key press.
|
||||||
// This is confusing from user perspective, so we want to avoid it.
|
// This is confusing from user perspective, so we want to avoid it.
|
||||||
if (!suggestionBar.isEmpty() && (newSelStart != candidatesEnd || newSelEnd != candidatesEnd)) {
|
if (
|
||||||
|
candidatesStart != -1 && candidatesEnd != -1
|
||||||
|
&& (newSelStart != candidatesEnd || newSelEnd != candidatesEnd)
|
||||||
|
&& !suggestionBar.isEmpty()
|
||||||
|
) {
|
||||||
acceptIncompleteSuggestion();
|
acceptIncompleteSuggestion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -509,18 +521,6 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void previousSuggestion() {
|
|
||||||
suggestionBar.scrollToSuggestion(-1);
|
|
||||||
textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void nextSuggestion() {
|
|
||||||
suggestionBar.scrollToSuggestion(1);
|
|
||||||
textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private boolean scheduleAutoAccept(int delay) {
|
private boolean scheduleAutoAccept(int delay) {
|
||||||
cancelAutoAccept();
|
cancelAutoAccept();
|
||||||
|
|
||||||
|
|
@ -624,7 +624,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
// for a more intuitive experience.
|
// for a more intuitive experience.
|
||||||
String word = suggestionBar.getCurrentSuggestion();
|
String word = suggestionBar.getCurrentSuggestion();
|
||||||
word = word.substring(0, Math.min(mInputMode.getSequenceLength(), word.length()));
|
word = word.substring(0, Math.min(mInputMode.getSequenceLength(), word.length()));
|
||||||
textField.setComposingTextWithHighlightedStem(word, mInputMode);
|
setComposingTextWithHighlightedStem(word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -665,6 +665,15 @@ public class TraditionalT9 extends KeyPadHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setComposingTextWithHighlightedStem(@NonNull String word) {
|
||||||
|
if (appHacks.setComposingTextWithHighlightedStem(word)) {
|
||||||
|
Logger.w("highlightComposingText", "Defective text field detected! Text highlighting disabled.");
|
||||||
|
} else {
|
||||||
|
textField.setComposingTextWithHighlightedStem(word, mInputMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void nextInputMode() {
|
private void nextInputMode() {
|
||||||
if (mInputMode.isPassthrough()) {
|
if (mInputMode.isPassthrough()) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
42
src/io/github/sspanak/tt9/ime/helpers/AppHacks.java
Normal file
42
src/io/github/sspanak/tt9/ime/helpers/AppHacks.java
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.github.sspanak.tt9.ime.helpers;
|
||||||
|
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import io.github.sspanak.tt9.ime.modes.InputMode;
|
||||||
|
|
||||||
|
public class AppHacks {
|
||||||
|
private final EditorInfo editorInfo;
|
||||||
|
private final TextField textField;
|
||||||
|
|
||||||
|
|
||||||
|
public AppHacks(EditorInfo inputField, TextField textField) {
|
||||||
|
this.editorInfo = inputField;
|
||||||
|
this.textField = textField;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isKindleInvertedTextField() {
|
||||||
|
return editorInfo != null && editorInfo.inputType == 1 && editorInfo.packageName.contains("com.amazon.kindle");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean setComposingTextWithHighlightedStem(@NonNull String word) {
|
||||||
|
if (isKindleInvertedTextField()) {
|
||||||
|
textField.setComposingText(word);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean onBackspace(InputMode inputMode) {
|
||||||
|
if (isKindleInvertedTextField()) {
|
||||||
|
inputMode.clearWordStem();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -274,13 +274,13 @@ public class TextField {
|
||||||
* the text will be in bold and italic.
|
* the text will be in bold and italic.
|
||||||
*/
|
*/
|
||||||
private CharSequence highlightText(CharSequence word, int start, int end, boolean highlightMore) {
|
private CharSequence highlightText(CharSequence word, int start, int end, boolean highlightMore) {
|
||||||
if (end < start || start < 0) {
|
if (end <= start || start < 0) {
|
||||||
Logger.w("tt9.util.highlightComposingText", "Cannot highlight invalid composing text range: [" + start + ", " + end + "]");
|
Logger.w("tt9.util.highlightComposingText", "Cannot highlight invalid composing text range: [" + start + ", " + end + "]");
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing to highlight in an empty word
|
// nothing to highlight in an empty word or if the target is beyond the last letter
|
||||||
if (word == null || word.length() == 0) {
|
if (word == null || word.length() == 0 || word.length() <= start) {
|
||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
|
|
@ -106,6 +107,7 @@ public class SuggestionsBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NonNull
|
||||||
public String getSuggestion(int id) {
|
public String getSuggestion(int id) {
|
||||||
if (id < 0 || id >= suggestions.size()) {
|
if (id < 0 || id >= suggestions.size()) {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue