Search code examples
androidandroid-studioandroid-edittextandroid-textinputlayout

Editext InputLayout.setError showing only at the first time


I'm trying to validate an input from Editext via TextWatcher and show an error with its InputLayout. The problem is, The InputLayout error is showing at the first time only the next time the input become invalid the InputLayout error is no longer showing.

I simply want to validate the inputted port, I want it to start at 2000 to 65535 and my layout is showing as dialog.

final Dialog dialog = new Dialog(PanelActivity.this,R.style.CustomDialog);
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
dialog.setCancelable(true);
dialog.setContentView(R.layout.port_layout);
final EditText ePort = (EditText) dialog.findViewById(R.id.input_port);
final TextInputLayout inputLayoutPort = (TextInputLayout)dialog.findViewById(R.id.input_layout_port);

ePort.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                if(s.length() > 1){
                    if(Integer.parseInt(String.valueOf(s)) < 2000 || Integer.parseInt(String.valueOf(s)) > 65535){
                        inputLayoutPort.setError("Port must be 2000 to 65535.");
                        //Inputted port is incorrect
                    }else{
                        inputLayoutPort.setErrorEnabled(false);
                        .... //Inputted port is correct
                    }
                }else{
                    inputLayoutPort.setError("Port must be 2000 to 65535.");
                    //Inputted port is incorrect
                }
            }

            @Override
            public void afterTextChanged(Editable s) {}
        });

dialog.show();

I already try to change it to, though it will work.

... //onTextChanged
        if(s.length() > 1){
            if(Integer.parseInt(String.valueOf(s)) < 2000 || Integer.parseInt(String.valueOf(s)) > 65535){
                inputLayoutPort.setError("Port must be 2000 to 65535.");
                inputLayoutPort.setErrorEnabled(true);
                //Inputted port is incorrect
            }else{
                inputLayoutPort.setErrorEnabled(false);
                .... //Inputted port is correct
            }
        }else{
            inputLayoutPort.setError("Port must be 2000 to 65535.");
            inputLayoutPort.setErrorEnabled(true);
            //Inputted port is incorrect
        }

but still, it is showing at the first time only the input become invalid.

This is the first I've used an InputLayout, I just follow the tutorial I found, but it seems like I'm missing something and I can't figure it out.

UPDATE: The below code is for my Inputlayout xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    //....

        <android.support.design.widget.TextInputLayout
            android:id="@+id/input_layout_port"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="12dp"
            android:layout_below="@+id/defaultValue"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:layout_centerHorizontal="true">

            <EditText
                android:id="@+id/input_port"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="Server Port"
                android:inputType="number"
                android:maxLength="5"
                android:nextFocusLeft="@id/input_port"
                android:nextFocusUp="@id/input_port"
                android:textAlignment="center"
                android:textStyle="bold" />

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

    //...
</RelativeLayout>

Solution

  • Based on your code, you can simplify the onTextChanged() as:

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {
    
        inputLayoutPort.setError("Port must be 2000 to 65535.");
    
        if(s.length() > 1 && !(Integer.parseInt(String.valueOf(s)) < 2000 || Integer.parseInt(String.valueOf(s)) > 65535)) {
            inputLayoutPort.setError(null);
        }
    }
    

    So, I'm setting the error message "Port must be 2000 to 65535." everytime the text in the edittext changes. Then, combining your two conditions s.length() > 1 and s lies between 2000 and 65535, I'm removing the error message by setting error to null.