EditText not updated after text changed in the TextWatcher

Karthz picture Karthz · Sep 15, 2011 · Viewed 14.3k times · Source

I have an EditText and a TextWatcher.

Skeleton of my code:

EditText x;
x.addTextChangedListener(new XyzTextWatcher());

XyzTextWatcher implements TextWatcher() {
    public synchronized void afterTextChanged(Editable text) {
        formatText(text);
    }
}

My formatText() method inserts some hyphens at some positions of the text.

private void formatText(Editable text) {
    removeSeparators(text);

    if (text.length() >= 3) {
        text.insert(3, "-");
    }
    if (text.length() >= 7) {
        text.insert(7, "-");
    }
}

private void removeSeparators(Editable text) {
    int p = 0;
    while (p < text.length()) {
        if (text.charAt(p) == '-') {
            text.delete(p, p + 1);
        } else {
            p++;
        }
    }
}

The problem I have is - what is displayed on my EditText isn't in sync with the Editable. When I debugged the code, I saw that the variable text (Editable) has the expected value, but what's shown on the EditText doesn't always match the Editable.

For example, when I have a text x = "123-456-789" I cut the text "456" from x manually. After formatting, my Editable has the value "123-789-" However, the value shown on my EditText is "123--789"

They have the same value in most cases though.

I assumed that the EditText IS the Editable and they should always match. Am I missing something?

Answer

slayton picture slayton · Sep 15, 2011

Ok, you never actually change the EditText just the Editable. Android EditTexts are not children of the Editable class. Strings are subclasses of the Editable class. The onTextChangedListener doesn't receive the EditText as an argument but the Editable/String displayed in the EditText. After you format the Editable with the hyphens you then need to update the EditText. Something like this should work fine:

class MyClass extends Activity{

    //I've ommited the onStart(), onPause(), onStop() etc.. methods

    EditText x;
    x.addTextChangedListener(new XyzTextWatcher());

    XyzTextWatcher implements TextWatcher() {
        public synchronized void afterTextChanged(Editable text) {
            String s = formatText(text);
            MyClass.this.x.setText(s);
        }
    }

}

To prevent the slowdown why not change the formatText method something like this?

private Editable formatText(Editable text) {
    int sep1Loc = 3;
    int sep2Loc = 7;

    if(text.length==sep1Loc)
    text.append('-');

    if(text.length==sep2Loc)
    text.append('-');

    return text;
}

Note: I haven't tested this