Search code examples
androidandroid-edittextandroid-textinputedittext

Cannot edit a TextInputEditText after setting an error on it in Android 6.0


I have a bunch of TextInputEditText's in my layout defined like so:

<android.support.design.widget.TextInputLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

   <android.support.design.widget.TextInputEditText
                android:id="@+id/confirmPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/registration_confirm_password"
                android:inputType="textPassword" />

</android.support.design.widget.TextInputLayout>

And when the users tries to submit the form, I have a validate method that checks each field and sets an error on invalid fields, like so:

if(confirmPassword.text.toString() != password.text.toString()) {
        confirmPassword.error = "Passwords don't match"
        confirmPassword.setOnKeyListener { _, _, _ ->
            confirmPassword.error = null
            true
        }
        valid = false
}

The OnKeyListener is there to remove the error as soon as the user starts correcting his mistake.

This code works perfectly in my emulators and on my device with Android 5.1.1. But on the device of one of my users, a Samsung Galaxy S6 Edge with Android 6.0, when he makes a mistake and a field has an error on it, he cannot edit it anymore.

Am I using TextInputEditText wrong? Is it a known bug? Is there a workaround?


Solution

  • onKey is Called when a hardware key is dispatched to a view. This allows listeners to get a chance to respond before the target view.

    Key presses in software keyboards will generally NOT trigger this method, although some may elect to do so in some situations. Do not assume a software input method has to be key-based; even if it is, it may use key presses in a different way than you expect, so there is no way to reliably catch soft input key presses.

    return True if the listener has consumed the event, false otherwise.

    When you return true from onKey method in setOnKeyListener you have consumed the event and event will not be sent to the view always return false from it if you want the view to react to key press in default way

    But better solution for you is to use addTextChangedListener instead of setOnKeyListener this way soft keyboard key press is better supported with your code:

    if(confirmPassword.text.toString() != password.text.toString()) {
                confirmPassword.error = "Passwords don't match"
                confirmPassword.addTextChangedListener (new TextWatcher {
                    afterTextChanged(Editable s) { 
                        // Nothing to do here 
                    }
    
                    beforeTextChanged(CharSequence s, int start, int count, int after) { 
                       // Nothing to do here 
                    }
    
                    onTextChanged(CharSequence s, int start, int before, int count) {
                        // When user start to edit, delete the error feedback 
                        confirmPassword.error = null
                    }
                });
    
        valid = false;          
    }
    

    As stated by View.OnKeyListener official doc:

    Interface definition for a callback to be invoked when a hardware key event is dispatched to this view. The callback will be invoked before the key event is given to the view. This is only useful for hardware keyboards; a software input method has no obligation to trigger this listener.