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
|
||||
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();
|
||||
// Logger.d("T9.onStartInput", "inputType: " + inputField.inputType + " fieldId: " + inputField.fieldId + " fieldName: " + inputField.fieldName + " packageName: " + inputField.packageName);
|
||||
onStart(inputField);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import java.util.List;
|
|||
import io.github.sspanak.tt9.Logger;
|
||||
import io.github.sspanak.tt9.R;
|
||||
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.InputType;
|
||||
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 {
|
||||
// internal settings/data
|
||||
private boolean isActive = false;
|
||||
@NonNull private AppHacks appHacks = new AppHacks(null, null);
|
||||
@NonNull private TextField textField = new TextField(null, null);
|
||||
@NonNull private InputType inputType = new InputType(null, null);
|
||||
@NonNull private final Handler autoAcceptHandler = new Handler(Looper.getMainLooper());
|
||||
|
|
@ -202,6 +204,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
protected void onStart(EditorInfo input) {
|
||||
inputType = new InputType(currentInputConnection, input);
|
||||
textField = new TextField(currentInputConnection, input);
|
||||
appHacks = new AppHacks(input, textField);
|
||||
|
||||
if (!inputType.isValid() || inputType.isLimited()) {
|
||||
// When the input is invalid or simple, let Android handle it.
|
||||
|
|
@ -242,6 +245,10 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
|
||||
public boolean onBackspace() {
|
||||
if (appHacks.onBackspace(mInputMode)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1. Dialer fields seem to handle backspace on their own and we must ignore it,
|
||||
// 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)
|
||||
|
|
@ -296,7 +303,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
if (mInputMode.shouldSelectNextSuggestion() && !isSuggestionViewHidden()) {
|
||||
nextSuggestion();
|
||||
onKeyScrollSuggestion(false, false);
|
||||
scheduleAutoAccept(mInputMode.getAutoAcceptTimeout());
|
||||
} else {
|
||||
getSuggestions();
|
||||
|
|
@ -311,9 +318,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
if (isSuggestionViewHidden()) {
|
||||
return performOKAction();
|
||||
} else {
|
||||
acceptCurrentSuggestion(KeyEvent.KEYCODE_ENTER);
|
||||
}
|
||||
|
||||
acceptCurrentSuggestion(KeyEvent.KEYCODE_ENTER);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -425,10 +432,9 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
}
|
||||
|
||||
cancelAutoAccept();
|
||||
if (backward) previousSuggestion();
|
||||
else nextSuggestion();
|
||||
suggestionBar.scrollToSuggestion(backward ? -1 : 1);
|
||||
mInputMode.setWordStem(suggestionBar.getCurrentSuggestion(), true);
|
||||
textField.setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion(), mInputMode);
|
||||
setComposingTextWithHighlightedStem(suggestionBar.getCurrentSuggestion());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -493,12 +499,18 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
|
||||
@Override
|
||||
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);
|
||||
|
||||
// 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.
|
||||
// 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
cancelAutoAccept();
|
||||
|
||||
|
|
@ -624,7 +624,7 @@ public class TraditionalT9 extends KeyPadHandler {
|
|||
// for a more intuitive experience.
|
||||
String word = suggestionBar.getCurrentSuggestion();
|
||||
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() {
|
||||
if (mInputMode.isPassthrough()) {
|
||||
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.
|
||||
*/
|
||||
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 + "]");
|
||||
return word;
|
||||
}
|
||||
|
||||
// nothing to highlight in an empty word
|
||||
if (word == null || word.length() == 0) {
|
||||
// nothing to highlight in an empty word or if the target is beyond the last letter
|
||||
if (word == null || word.length() == 0 || word.length() <= start) {
|
||||
return word;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.DefaultItemAnimator;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
|
|
@ -106,6 +107,7 @@ public class SuggestionsBar {
|
|||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public String getSuggestion(int id) {
|
||||
if (id < 0 || id >= suggestions.size()) {
|
||||
return "";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue