Skip to content

Commit

Permalink
Fix[touch_char_input]: use TextWatcher instead of onTextChanged override
Browse files Browse the repository at this point in the history
Avoids a bug on some devices caused by setText called by the framework early
  • Loading branch information
artdeell committed Jan 15, 2025
1 parent b28fc4a commit 9514685
Showing 1 changed file with 37 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import android.annotation.SuppressLint;
import android.content.Context;
import android.text.Editable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.inputmethod.InputMethodManager;
Expand Down Expand Up @@ -34,31 +35,6 @@ public TouchCharInput(@NonNull Context context, @Nullable AttributeSet attrs, in
private boolean mIsDoingInternalChanges = false;
private CharacterSenderStrategy mCharacterSender;

/**
* We take the new chars, and send them to the game.
* If less chars are present, remove some.
* The text is always cleaned up.
*/
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if(mIsDoingInternalChanges)return;
if(mCharacterSender != null){
for(int i=0; i < lengthBefore; ++i){
mCharacterSender.sendBackspace();
}

for(int i=start, count = 0; count < lengthAfter; ++i){
mCharacterSender.sendChar(text.charAt(i));
++count;
}
}

//Reset the keyboard state
if(text.length() < 1) clear();
}


/**
* When we change from app to app, the keyboard gets disabled.
* So, we disable the object
Expand Down Expand Up @@ -142,6 +118,9 @@ public void setCharacterSender(CharacterSenderStrategy characterSender){

/** This function deals with anything that has to be executed when the constructor is called */
private void setup(){
// Using TextWatcher instead of overriding onTextChanged because some Huawei firmware
// calls setText in constructor, causing havoc for our listener
addTextChangedListener(new InputTextWatcher());
setOnEditorActionListener((textView, i, keyEvent) -> {
sendEnter();
clear();
Expand All @@ -151,5 +130,38 @@ private void setup(){
clear();
disable();
}
private class InputTextWatcher implements android.text.TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

/**
* We take the new chars, and send them to the game.
* If less chars are present, remove some.
* The text is always cleaned up.
*/
@Override
public void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
if(mIsDoingInternalChanges) return;
if(mCharacterSender != null){
for(int i=0; i < lengthBefore; ++i){
mCharacterSender.sendBackspace();
}

for(int i=start, count = 0; count < lengthAfter; ++i){
mCharacterSender.sendChar(text.charAt(i));
++count;
}
}
}

@Override
public void afterTextChanged(Editable editable) {
if(mIsDoingInternalChanges) return;
// Moved from onTextChanged because "It is an error to attempt to make changes to s from this callback."
// reference: https://developer.android.com/reference/android/text/TextWatcher#onTextChanged(java.lang.CharSequence,%20int,%20int,%20int)
if(editable.length() < 1) clear();
}
}
}

0 comments on commit 9514685

Please sign in to comment.