2016-12-05 393 views
4

我想有一个EditText的背景作为一个“正常”的EditText但错误处理的TextInputEditText(错误信息出现在底部,而不是“!”可绘制出现)。不要更改错误的TextInputLayout背景

我得到了这样的事情:

<android.support.design.widget.TextInputLayout 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    app:setError="@{viewModel.error}"> 

    <android.support.design.widget.TextInputEditText 

     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 

     android:background="@drawable/simple_edit_text_background" 
     android:ellipsize="end" 
     android:inputType="textMultiLine|textNoSuggestions" 
     android:text="@={viewModel.value}" 

     style="@style/MyEditTextStyle" /> 

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

但似乎当我设置错误的TextInputLayout它改变了背景绘制(这是在正常TextInputEditText,下划线),以错误的颜色TextView中。

所以这是我的EditText看起来像:

private void updateEditTextBackground() { 
    if (mEditText == null) { 
     return; 
    } 

    Drawable editTextBackground = mEditText.getBackground(); 
    if (editTextBackground == null) { 
     return; 
    } 

    ensureBackgroundDrawableStateWorkaround(); 

    if (android.support.v7.widget.DrawableUtils.canSafelyMutateDrawable(editTextBackground)) { 
     editTextBackground = editTextBackground.mutate(); 
    } 

    if (mErrorShown && mErrorView != null) { 
     // Set a color filter of the error color 
     editTextBackground.setColorFilter(
       AppCompatDrawableManager.getPorterDuffColorFilter(
         mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); 
    } else if (mCounterOverflowed && mCounterView != null) { 
     // Set a color filter of the counter color 
     editTextBackground.setColorFilter(
       AppCompatDrawableManager.getPorterDuffColorFilter(
         mCounterView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); 
    } else { 
     // Else reset the color filter and refresh the drawable state so that the 
     // normal tint is used 
     DrawableCompat.clearColorFilter(editTextBackground); 
     mEditText.refreshDrawableState(); 
    } 
} 
该更新的研究背景颜色

代码的块是: enter image description here

我们可以以下方法中看到它在TextInputLayout的代码这里:

if (mErrorShown && mErrorView != null) { 
    // Set a color filter of the error color 
    editTextBackground.setColorFilter(
      AppCompatDrawableManager.getPorterDuffColorFilter(
        mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN)); 
} 

因为这种方法是私人的我不能重写它,因为我仍然希望我的错误TextV视图的颜色是红色的我目前看不到任何解决方案。任何想法?

一个解决方案可能会重置背景颜色为setError本来被调用后的默认值,但他们的任何回调,如onError方法将被解雇,一旦错误设置为TextView/EditText?

回答

13

我设法通过重写TextInputLayout这样来解决这个自己:

public class NoChangingBackgroundTextInputLayout extends TextInputLayout { 
    public NoChangingBackgroundTextInputLayout(Context context) { 
     super(context); 
    } 

    public NoChangingBackgroundTextInputLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public NoChangingBackgroundTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    public void setError(@Nullable CharSequence error) { 
     ColorFilter defaultColorFilter = getBackgroundDefaultColorFilter(); 
     super.setError(error); 
     //Reset EditText's background color to default. 
     updateBackgroundColorFilter(defaultColorFilter); 
    } 

    @Override 
    protected void drawableStateChanged() { 
     ColorFilter defaultColorFilter = getBackgroundDefaultColorFilter(); 
     super.drawableStateChanged(); 
     //Reset EditText's background color to default. 
     updateBackgroundColorFilter(defaultColorFilter); 
    } 

    /** 
    * If {@link #getEditText()} is not null & {@link #getEditText()#getBackground()} is not null, 
    * update the {@link ColorFilter} of {@link #getEditText()#getBackground()}. 
    * @param colorFilter {@link ColorFilter} 
    */ 
    private void updateBackgroundColorFilter(ColorFilter colorFilter) { 
     if(getEditText() != null && getEditText().getBackground() != null) 
      getEditText().getBackground().setColorFilter(colorFilter); 
    } 

    /** 
    * Get the EditText's default background color. 
    * @return {@link ColorFilter} 
    */ 
    @Nullable 
    private ColorFilter getBackgroundDefaultColorFilter() { 
     ColorFilter defaultColorFilter = null; 
     if(getEditText() != null && getEditText().getBackground() != null) 
      defaultColorFilter = DrawableCompat.getColorFilter(getEditText().getBackground()); 
     return defaultColorFilter; 
    } 

所以我们可以看到它,它的EditText的背景重置为默认颜色SETERROR被称为后还要在方法drawableStateChanged()因为红色滤镜在丢失/获得EditText的焦点时也会设置错误。

我不相信这是最好的解决方案,但如果我没有得到更好的解决方案,我会在此期间将其标记为已解决。

+0

很好的解决方案。又一次,我们需要使用黑客来克服Android的糟糕设计。 – Storix

+0

梦幻般的解决方案.... –

+0

@覆盖! – Killer

0

安排https://stackoverflow.com/a/40379564/2914140https://stackoverflow.com/a/44744941/2914140接受的解决方案,我写了另一类。当EditText具有特殊背景(background_1)时,它会在出现错误时更改为background_2。当错误消失时,它会再次返回到background_1。没有执行红色填充。

public class YourTextInputLayout extends TextInputLayout { 

    private Drawable drawable1; // Normal background. 
    private Drawable drawable2; // Error background. 

    public YourTextInputLayout(Context context) { 
     super(context); 
    } 

    public YourTextInputLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public YourTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

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

     replaceBackground(); 
    } 

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

     replaceBackground(); 
    } 

    public void setDrawable1(Drawable drawable) { 
     this.drawable1 = drawable; 
    } 

    public void setDrawable2(Drawable drawable) { 
     this.drawable2 = drawable; 
    } 

    private void replaceBackground() { 
     EditText editText = getEditText(); 
     if (editText != null) { 
      editText.setBackground(isErrorEnabled() ? drawable2 : drawable1); 
      Drawable drawable = editText.getBackground(); 
      if (drawable != null) { 
       drawable.clearColorFilter(); 
      } 
     } 
    } 
} 

在的onCreate()/ onCreateView(初始化后您的活动/片段调用):

YourTextInputLayout inputLayout = ...; 
inputLayout.setDrawable1(ContextCompat.getDrawable(getContext(), R.drawable.background_1)); 
inputLayout.setDrawable2(ContextCompat.getDrawable(getContext(), R.drawable.background_2)); 

在你的XML布局被称之为:

<com.example.package.YourTextInputLayout 
    android:id="@+id/container" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" > 

    <EditText 
     ... 
1

我有同样的问题;经过搜索和打击&来看,我发现这样简单的方法来解决这个problem-

试试这个最简单的办法 -

   <android.support.design.widget.TextInputLayout 
        android:id="@+id/til_description" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:layout_marginTop="8dp" 
        app:errorText="@{feedbackViewModel.descError}" 
        > 

        <EditText 
         style="@style/TextInputLayoutEditText" 
         android:layout_width="match_parent" 
         android:layout_height="wrap_content" 
         android:background="@drawable/desc_field_selector" 
         **android:paddingTop="10dp"** 
         **android:paddingBottom="7dp"** 
         android:gravity="top|left" 
         android:hint="@string/description" 
         android:inputType="textMultiLine" 
         android:lines="4" 
         android:onTextChanged="@{(text, start, before, count) -> feedbackViewModel.onDescriptionTextChanged(text)}" 
         android:scrollHorizontally="false" 
         android:scrollbarStyle="insideInset" 
         android:scrollbars="vertical" 
         android:text="@={feedbackViewModel.description}"/> 

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

而且机器人:背景= “@绘制/ desc_field_selector” -

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/rectangle_blue_border_background" 
      android:state_pressed="true"/> 
    <item android:drawable="@drawable/rectangle_blue_border_background" 
      android:state_enabled="true" 
      android:state_focused="true" 
      android:state_window_focused="true"/> 
    <item android:drawable="@drawable/rectangle_black_border_background"/> 
</selector> 

查阅原始形状(@绘制/ rectangle_black_border_background)会像 -

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    **<item android:state_focused="false" android:top="5dp">** 
     <shape> 
      **<solid android:color="@android:color/transparent"/>** 
      <stroke android:width="1dp" android:color="@android:color/secondary_text_light"/> 
      <corners android:radius="5dp"/> 
     </shape> 
    </item> 
</layer-list> 

和原来的形状(@绘制/ rectangle_blue_border_background)会像 -

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    **<item android:state_focused="true" android:top="5dp">** 
     <shape> 
      **<solid android:color="@android:color/transparent"/>** 
      <stroke android:width="@dimen/one_dip" android:color="@color/colorAccent"/> 
      <corners android:radius="5dp"/> 
     </shape> 
    </item> 
</layer-list> 

注意 -的**线条太重要 -

  1. paddingTop =” 10dp“android:paddingBottom =”7dp“ - >将移动浮动标签从边界形状足够多,否则它会看起来不太好。
  2. android:top =“5dp” - 对于将浮动标签移动到足以形成矩形非常重要。
  3. 坚实的android:颜色=“@安卓:彩色/透明” - 这种固体形状的颜色是透明的,所以当发生错误,你会看到的只是一个透明的颜色。看看 -

**注意 - **根据需要更改您的填充值和项目最大值以及纯色(您也可以删除纯色线)。

enter image description here

就是这样:-)快乐编码+1