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:
AFTER setError("mandatory field")
AFTER setError(null)
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)
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!!!
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 :)
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);
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>
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.
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);
}
来源:https://stackoverflow.com/questions/34182435/android-textinputlayout-changes-edittext-style-after-setting-error-to-null