2016-12-05 99 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