13

for the first time I'm using the new Android's widget TextInputLayout, it's very nice but I'm facing some problem using setError method

this is my xml

<android.support.design.widget.TextInputLayout
    android:id="@+id/userData_txtNameWrapper"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:textColorHint="@color/light_gray"
    app:hintTextAppearance="@style/TextAppearence.App.TextInputLayout">
    <EditText
        android:id="@+id/userData_txtName"
        style="@style/bold_textbox_style"
        android:layout_width="match_parent"
        android:layout_height="@dimen/textinut_height"
        android:layout_margin="5dp"
        android:hint="name"
        android:imeOptions="actionNext"
        android:inputType="text"
        android:paddingTop="10dp"
        android:textSize="@dimen/medium_text"/>
</android.support.design.widget.TextInputLayout>

WHAT IS HAPPENING:

when I run

setError("error message") 

the whole EditText background and hint text color becomes red and since here it's fine. The issue is when I run

setError(null) 

the EditText's style is completely changed from the original one.

STARTING SITUATION:

unfocused unfocused focused focused

AFTER setError("mandatory field")

enter image description here

AFTER setError(null)

enter image description here

I made a lot of researches but couldn't find anything helpful, what the hell should the problem be??

UPDATE

Investigating in the android source code of setError() method I found this

public void setError(@Nullable CharSequence error) {
    if (!mErrorEnabled) {
        if (TextUtils.isEmpty(error)) {
            // If error isn't enabled, and the error is empty, just return
            return;
        }
        // Else, we'll assume that they want to enable the error functionality
        setErrorEnabled(true);
    }
    if (!TextUtils.isEmpty(error)) {
        ViewCompat.setAlpha(mErrorView, 0f);
        mErrorView.setText(error);
        ViewCompat.animate(mErrorView)
                .alpha(1f)
                .setDuration(ANIMATION_DURATION)
                .setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
                .setListener(new ViewPropertyAnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(View view) {
                        view.setVisibility(VISIBLE);
                    }
                })
                .start();
        // Set the EditText's background tint to the error color
        mErrorShown = true;
        updateEditTextBackground();
        updateLabelVisibility(true);
    } else {
        if (mErrorView.getVisibility() == VISIBLE) {
            ViewCompat.animate(mErrorView)
                    .alpha(0f)
                    .setDuration(ANIMATION_DURATION)
                    .setInterpolator(AnimationUtils.FAST_OUT_SLOW_IN_INTERPOLATOR)
                    .setListener(new ViewPropertyAnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(View view) {
                            view.setVisibility(INVISIBLE);
                            updateLabelVisibility(true);
                        }
                    }).start();
            // Restore the 'original' tint, using colorControlNormal and colorControlActivated
            mErrorShown = false;
            updateEditTextBackground();
        }
    }


    private void updateEditTextBackground() {
        if (mErrorShown && mErrorView != null) {
            // Set the EditText's background tint to the error color
            ViewCompat.setBackgroundTintList(mEditText,
                    ColorStateList.valueOf(mErrorView.getCurrentTextColor()));
        } else if (mCounterOverflowed && mCounterView != null) {
            ViewCompat.setBackgroundTintList(mEditText,
                    ColorStateList.valueOf(mCounterView.getCurrentTextColor()));
        } else {
            final TintManager tintManager = TintManager.get(getContext());
            ViewCompat.setBackgroundTintList(mEditText,
                    tintManager.getTintList(R.drawable.abc_edit_text_material));
        }
    }

and debugging the code I found that the piece of code getting executed in updateEditTextBackground() is the following

final TintManager tintManager = TintManager.get(getContext());
ViewCompat.setBackgroundTintList(mEditText,
        tintManager.getTintList(R.drawable.abc_edit_text_material));

It seem that android is arbitrary replacing the EditText's background tint. I tryed to create a file in my drawable folder named abc_edit_text_material.xml with this code

<inset xmlns:android="http://schemas.android.com/apk/res/android"
       android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
       android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
       android:insetTop="@dimen/abc_edit_text_inset_top_material"
       android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">

    <selector>
        <item android:state_enabled="false" android:drawable="@color/white"/>
        <item android:state_pressed="false" android:state_focused="false" android:drawable="@color/white"/>
        <item android:drawable="@color/white"/>
    </selector>

</inset>

but this is the result after setError(null)

enter image description here

Moreover I noticed that the problem exists only when I run setError("error message") and then setError(null)

UPDATE 2 This is the code I use to validate my inputs

public boolean validateInputs() {
    mTxtNameWrapper.setError(null);
    mTxtLastNameWrapper.setError(null);
    mTxtEmailWrapper.setError(null);
    mTxtCountryWrapper.setError(null);
    mTxtIdCardWrapper.setError(null);
    mTxtFiscalCodeWrapper.setError(null);
    mLblDocTypeError.setVisibility(View.GONE);
    if (Strings.isNullOrEmpty(mTxtName.getText().toString())) {
        mTxtNameWrapper.setError("Mandatory field");
        return false;
    }
    if (Strings.isNullOrEmpty(mTxtLastName.getText().toString())) {
        mTxtLastNameWrapper.setError("Mandatory field");
        return false;
    }
    if (Strings.isNullOrEmpty(mTxtEmail.getText().toString())) {
        mTxtEmailWrapper.setError("Mandatory field");
        return false;
    }
    if (!android.util.Patterns.EMAIL_ADDRESS.matcher(mTxtEmail.getText().toString()).matches()) {
        mTxtEmailWrapper.setError("Invalid email format");
        return false;
    }
    if (Strings.isNullOrEmpty(mTxtCountry.getText().toString())) {
        mTxtCountryWrapper.setError("Mandatory field");
        return false;
    }
    if (mRdgIdType.getCheckedRadioButtonId() == -1) {
        mLblDocTypeError.setText("Select a document type");
        mLblDocTypeError.setVisibility(View.VISIBLE);
        return false;
    }
    if (Strings.isNullOrEmpty(mTxtIdCard.getText().toString())) {
        mTxtIdCardWrapper.setError("Mandatory field");
        return false;
    }
    if (Strings.isNullOrEmpty(mTxtFiscalCode.getText().toString())) {
        mTxtFiscalCodeWrapper.setError("Mandatory field");
        return false;
    }
    return true;
}

I'm going crazy!!!

Apperside
  • 3,542
  • 2
  • 38
  • 65

6 Answers6

6

I ran into similar problem and found a simple solution for it. This problem occurs if we set a custom background drawable/color to the EditText inside the TextInputLayout. Solution to this would be to subclass the the TextInputLayout and override the setError() and drawableStateChanged() methods and set our custom drawable/color as the EditText's background again. For Example, I had a rounded corner drawable set for my EditText's background, below is my subclass,

public class RoundedBorderedTextInputLayout extends TextInputLayout {
    private Context context;

    public RoundedBorderedTextInputLayout(Context context) {
        super(context);
        this.context = context;
    }

    public RoundedBorderedTextInputLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }

    public RoundedBorderedTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();

        EditText editText = getEditText();
        if(editText != null) {
            editText.setBackground(ContextCompat.getDrawable(this.context, R.drawable.custom_rounded_edittext));
        }
    }

    @Override
    public void setError(@Nullable final CharSequence error) {
        super.setError(error);

        EditText editText = getEditText();
        if(editText != null) {
            editText.setBackground(ContextCompat.getDrawable(this.context, R.drawable.custom_rounded_edittext));
        }
    }
}

And then use your custom class in the xml,

<com.example.RoundedBorderedTextInputLayout
                android:id="@+id/text_input_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <EditText
                    android:id="@+id/edittext"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:inputType="textPassword"/>

  </com.example.RoundedBorderedTextInputLayout>

Hope this helps. Happy Android coding :)

user_1989
  • 375
  • 4
  • 10
  • 1
    The only thing which helped me was combining this anser and the one with setting background like this: yourEditText.getBackground().mutate().setColorFilter( ContextCompat.getColor(getContext() , R.color.somecolor), PorterDuff.Mode.SRC_ATOP); – shtolik Jan 23 '17 at 12:04
4

You just have to change the color back to whatever you want after setting the error to null. Something like:

yourEditText.setError(null);
yourEditText.getBackground().mutate().setColorFilter(
            ContextCompat.getColor(getContext() , R.color.somecolor),
            PorterDuff.Mode.SRC_ATOP);
iflp
  • 1,742
  • 17
  • 25
4

This was a bug in support:design:23.2.0 (and possibly older versions) it was reported as an issue here and has been fixed in the 23.3.0 update

kingdonnaz
  • 101
  • 5
0

set the style of your textinput

<style name="TextAppearence.App.TextInputLayout" parent="@android:style/TextAppearance">
        <item name="android:textColor">@color/colorPrimaryDark</item>
        <item name="android:textColorHint">@color/colorPrimaryDark</item>
        <item name="android:textSize">14sp</item>
        <item name="colorAccent">@color/colorPrimaryDark</item>
        <item name="colorControlNormal">@color/colorPrimaryDark</item>
        <item name="colorControlActivated">@color/colorPrimaryDark</item>
    </style>

Put below code where you setError(null)

     txt.setError(null);

//for plain white backgorund  
    editText.setBackgroundColor(getResources().getColor(android.R.color.white));

//or if you want any other than
editText.setBackgroundResource(R.drawable.border);

where border is my xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/listview_background_shape">
    <stroke android:width="2dp" android:color="#ff207d94" />
    <padding android:left="2dp"
        android:top="2dp"
        android:right="2dp"
        android:bottom="2dp" />
    <corners android:radius="5dp" />
    <solid android:color="#ffffffff" />
</shape>
H Raval
  • 1,903
  • 17
  • 39
  • already had a similar style with textColor, textColorHint and textSIze, added colorAccent,colorControlNormal and colorControlActivated respectively valorized with blue,red and yellow but nothing is changed.. – Apperside Dec 10 '15 at 09:53
  • – Apperside Dec 10 '15 at 10:02
  • no....not textinput layout style....i am asking for your edittext style....the bold_textbox_style – H Raval Dec 10 '15 at 10:04
  • – Apperside Dec 10 '15 at 10:31
0

I have a trick to solve this problem simply:

1,new a class extend android.support.design.widget.TextInputEditText ; 2,overrvide getBackground() method ,make it return null;

becasue the method updateEditTextBackground() in TextInputLayout will judge if editText's background drawable is null,and now always return null,result is editText's background will not be changed by error text color.

peng gao
  • 81
  • 5
0

got solution for only setError in this link

i.e. i have used custom TextInputLayout

this is my custom TextInputLayout

<com.adminworksite.Design.NoChangingBackgroundTextInputLayout
                        android:id="@+id/city_til_of_job_create"
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:layout_below="@+id/tv_placeholder_five"
                        android:layout_marginLeft="@dimen/left_right"
                        android:layout_marginRight="@dimen/left_right"
                        app:counterEnabled="true"
                        app:counterMaxLength="35">

                        <EditText
                            android:id="@+id/city_et_of_job_create"
                            android:layout_width="match_parent"
                            android:layout_height="wrap_content"
                            android:background="@drawable/edittext_background"
                            android:inputType="text"
                            android:paddingLeft="@dimen/left_right"
                            android:paddingRight="@dimen/left_right" />
                    </com.adminworksite.Design.NoChangingBackgroundTextInputLayout>

but if i set length limit to TextInputLayout i.e.

app:counterEnabled="true"
app:counterMaxLength="35"

the color still shows when limit exceeds and also changes color to pink

so i build one solution for it used addTextChangedListener to that edit text and set background by code

code snippet

editText.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() == 0) {
                    textInputLayout.setErrorEnabled(true);
                    textInputLayout.setError("Input should not be empty!");
                } else {
                    textInputLayout.setErrorEnabled(false);
                }
            }

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


private void setBackgroundToEt(EditText editText) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            editText.setBackground(getResources().getDrawable(R.drawable.edittext_background));
        }
    }

and inside validation method in the end, i have again used set background to my editText

code snippet:

private boolean validateInputs() {
//validation code...
setBackgroundToEt(editText);
}
LEGEND MORTAL
  • 336
  • 3
  • 18