Grant Ojanen
Grant Ojanen

Reputation: 188

Android EditText error is reset after maxLength is reached

I'm trying to use setError() and use the maxLength attribute on an EditText view, but after maxLength is reached and the user continues to type the error disappears. What is the proper place to call setError(), so that it doesn't get removed in this situation?

XML code

<EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/myEditText"
        android:maxLength="5"/>

Java Code

EditText myEditText = findViewById(R.id.myEditText);
myEditText.addTextChangedListener(new MyTextWatcher(myEditText));

Test TextWatcher that always sets error message.

private class MyTextWatcher implements TextWatcher {
    private EditText view;
    public MyTextWatcher(EditText editText) {view = editText;}
    @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {}
    @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) {}
    @Override public void afterTextChanged(Editable editable) {
        view.setError("setError worked");
    }
}

My testing device: Android 8.1 and software keyboard

Upvotes: 2

Views: 673

Answers (1)

Grant Ojanen
Grant Ojanen

Reputation: 188

I found a solution using a InputFilter in addition to a TextWatcher.

Because there isn't an easy way to access the maxLength attribute in Java, I created an integer resource for it. This way the max length can be managed in one stop.

XML for EditText view

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/myEditText"
    android:maxLength="@integer/myMaxLength"/>

XML for integer resource

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <integer name="myMaxLength">5</integer>
</resources>

Java setting up the InputFilter. The new filter is added to the EditText view's current filters.

final EditText myEditText = findViewById(R.id.myEditText);
myEditText.addTextChangedListener(new MyTextWatcher(myEditText));
final int myMaxLength = getResources().getInteger(R.integer.myMaxLength);
InputFilter filter = new InputFilter() {
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dstart, int dend) {
        if (myEditText.getText().length() >= myMaxLength) {
            myEditText.setError("setError worked (InputFilter)");
        }
        return null;
    }
};
InputFilter[] oldFilters = myEditText.getFilters();
InputFilter[] newFilters = new InputFilter[oldFilters.length+1];
System.arraycopy(oldFilters, 0, newFilters, 0, oldFilters.length);
newFilters[newFilters.length-1] = filter;
myEditText.setFilters(newFilters);

Java for the TextWatcher

private class MyTextWatcher implements TextWatcher {
    private EditText view;
    public MyTextWatcher(EditText editText) {view = editText;}
    @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {view.setError("Error Message");}
    @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) {view.setError("Error Message");}
    @Override public void afterTextChanged(Editable editable) {
        view.setError("setError worked (TextWatcher)");
    }
}

Upvotes: 1

Related Questions