I need to detect text changes in an EditText. I've tried TextWatcher, but it doesn't work in a way I would expect it to. Take the onTextChanged method:
public void onTextChanged( CharSequence s, int start, int before, int count )
Say I have the text "John" in already in the EditText. If press another key, "e", s
will be "Johne", start
will be 0, before
will be 4, and count
will be 5. The way I would expect this method to work would be the difference between what the EditText previously was, and what it's about to become.
So I would expect:
s = "Johne"
start = 4 // inserting character at index = 4
before = 0 // adding a character, so there was nothing there before
count = 1 // inserting one character
I need to be able to detect individual changes every time a key is pressed. So if I have text "John", I need to know "e" was added at index 4. If I backspace "e", I need to know "e" was removed from index 4. If I put the cursor after "J" and backspace, I need to know "J" was removed from index 0. If I put a "G" where "J" was, I want to know "G" replaced "J" at index 0.
How can I achieve this? I can't think of a reliable way to do this.
Use a textwatcher and do the diff yourself. store the previous text inside the watcher, and then compare the previous text to whatever sequence you get onTextChanged. Since onTextChanged is fired after every character, you know your previous text and the given text will differ by at most one letter, which should make it simple to figure out what letter was added or removed where. ie:
new TextWatcher(){
String previousText = theEditText.getText();
@Override
onTextChanged(CharSequence s, int start, int before, int count){
compare(s, previousText); //compare and do whatever you need to do
previousText = s;
}
...
}
The best approach you can follow to identify text changes.
var previousText = ""
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
previousText = s.toString()
}
override fun onTextChanged(newText: CharSequence?, start: Int, before: Int, count: Int) {
val position = start + before ;
if(newText!!.length > previousText.length){ //Character Added
Log.i("Added Character", " ${newText[position]} ")
Log.i("At Position", " $position ")
} else { //Character Removed
Log.i("Removed Character", " ${previousText[position-1]} ")
Log.i("From Position", " ${position-1} ")
}
}
override fun afterTextChanged(finalText: Editable?) { }
You need to store and update the previous CharSequence every time the text is changed. You can do so by implementing the TextWatcher.
Example:
final CharSequence[] previousText = {""};
editText.addTextChangedListener(new TextWatcher()
{
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
}
@Override public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
{
if(i1 > 0)
{
System.out.println("Removed Chars Positions & Text:");
for(int index = 0; index < i1; index++)
{
System.out.print((i + index) + " : " + previousText[0].charAt(i + index)+", ");
}
}
if(i2 > 0)
{
System.out.println("Inserted Chars Positions & Text:");
for(int index = 0; index < i2; index++)
{
System.out.print((index + i) + " : " + charSequence.charAt(i + index)+", ");
}
System.out.print("\n");
}
previousText[0] = charSequence.toString();//update reference
}
@Override public void afterTextChanged(Editable editable)
{
}
});
来源:https://stackoverflow.com/questions/9459489/detect-changes-in-edittext-textwatcher-ineffective