【问题标题】:android TextInputLayout changes EditText style after setting error to nullandroid TextInputLayout 将错误设置为 null 后更改 EditText 样式
【发布时间】:2015-12-09 15:20:36
【问题描述】:

我第一次使用新的 Android 的小部件 TextInputLayout,它非常好,但是我在使用 setError 方法时遇到了一些问题

这是我的 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>

发生了什么:

当我跑步时

setError("error message") 

整个 EditText 背景和提示文本颜色变为红色,因为这里没问题。问题是当我运行时

setError(null) 

EditText 的样式完全改变了原来的样式。

开始情况:

注意力不集中 专注

之后 setError("mandatory field")

之后 setError(null)

我做了很多研究,但找不到任何有用的东西,这到底是什么问题??

更新

setError()方法的android源码发现了这个

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));
        }
    }

调试代码发现updateEditTextBackground()中执行的代码如下

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

看来android 是随意替换EditText 的背景色调。我尝试使用此代码在名为 abc_edit_text_material.xml 的可绘制文件夹中创建一个文件

<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>

但这是setError(null)之后的结果

此外,我注意到问题仅在我运行 setError("error message") 然后 setError(null) 时才存在

更新 2 这是我用来验证输入的代码

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;
}

我要疯了!!!

【问题讨论】:

  • setError(null) => clearError()?
  • 你确定有这种方法吗?
  • setErrorEnabled(false)?
  • 请您在使用 setError 时完成代码。

标签: android android-textinputlayout


【解决方案1】:

我遇到了类似的问题,并找到了一个简单的解决方案。如果我们在TextInputLayout 中为EditText 设置自定义背景可绘制/颜色,则会出现此问题。对此的解决方案是将TextInputLayout 子类化并覆盖setError()drawableStateChanged() 方法,并将我们的自定义drawable/颜色再次设置为EditText's 背景。例如,我为EditText's 背景设置了一个圆角drawable,下面是我的子类,

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));
        }
    }
}

然后在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>

希望这会有所帮助。快乐的 Android 编码:)

【讨论】:

  • 唯一帮助我的是将这个分析器和一个设置背景的分析器结合起来,如下所示: yourEditText.getBackground().mutate().setColorFilter( ContextCompat.getColor(getContext() , R.color .somecolor), PorterDuff.Mode.SRC_ATOP);
【解决方案2】:

在将错误设置为 null 后,您只需将颜色更改回您想要的任何颜色。类似的东西:

yourEditText.setError(null);
yourEditText.getBackground().mutate().setColorFilter(
            ContextCompat.getColor(getContext() , R.color.somecolor),
            PorterDuff.Mode.SRC_ATOP);

【讨论】:

    【解决方案3】:

    这是support:design:23.2.0(可能还有旧版本)中的一个错误,它被报告为一个问题here 并且已经修复在23.3.0update

    【讨论】:

    • @Ajinkya 抱歉刚刚修复了链接
    • 问题已在 compile 'com.android.support:design:23.3.0' 中修复
    【解决方案4】:

    设置文本输入的样式

    <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>
    

    把下面的代码放在你设置Error(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);
    

    边框是我的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>
    

    【讨论】:

    • 已经有了与 textColor、textColorHint 和 textSIze 类似的样式,添加了 colorAccent、colorControlNormal 和 colorControlActivated 分别用蓝色、红色和黄色进行了调整,但没有任何改变..
    • no....不是 textinput 布局样式....我要求您提供 edittext 样式....bold_textbox_style
    【解决方案5】:

    我有个小技巧可以简单的解决这个问题:

    1、新建一个类扩展android.support.design.widget.TextInputEditText; 2、覆盖getBackground()方法,使其返回null;

    因为TextInputLayout中的updateEditTextBackground()方法会判断editText的背景drawable是否为null,现在总是返回null,结果是editText的背景不会被错误文本颜色改变。

    【讨论】:

      【解决方案6】:

      在这个 link 中只找到了 setError 的解决方案

      即我使用了自定义 TextInputLayout

      这是我的自定义 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>
      

      但如果我将长度限制设置为 TextInputLayout 即

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

      超过限制时颜色仍然显示,并且颜色变为粉红色

      所以我为它构建了一个解决方案,它使用 addTextChangedListener 来编辑文本和 通过代码设置背景

      代码sn-p

      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));
              }
          }
      

      最后在内部验证方法中,我再次将背景设置为我的editText

      代码sn-p:

      private boolean validateInputs() {
      //validation code...
      setBackgroundToEt(editText);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-10-24
        • 2016-09-25
        • 1970-01-01
        • 2020-05-21
        • 1970-01-01
        • 2015-10-14
        • 2018-10-12
        • 1970-01-01
        相关资源
        最近更新 更多