web-dev-qa-db-ja.com

エラー時にTextInputLayoutの背景を変更しないでください

背景が「通常の」EditTextであるが、TextInputEditTextのエラー処理(「!」ドローアブルは表示されず、下部にエラーメッセージが表示される)を伴うEditTextが必要です。

私はこのようなものを得ました:

<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がどのように見えるかです: enter image description here

次のメソッド内のTextInputLayoutのコードで確認できます。

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

背景色を更新するコードのブロックはここにあります:

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

このメソッドはプライベートなので、オーバーライドできません。また、エラーTextViewの色を赤にしたいので、これまでのところ解決策はありません。何か案が?

1つの解決策は、setErrorが呼び出された直後に背景色をデフォルト値にリセットすることですが、エラーがに設定されると発生するonErrorのようなメソッドを持つコールバックです。 TextView/EditText?

13
MHogge

私はこのように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);
    }

    private void updateBackgroundColorFilter(ColorFilter colorFilter) {
        if(getEditText() != null && getEditText().getBackground() != null)
            getEditText().getBackground().setColorFilter(colorFilter);
    }

    @Nullable
    private ColorFilter getBackgroundDefaultColorFilter() {
        ColorFilter defaultColorFilter = null;
        if(getEditText() != null && getEditText().getBackground() != null)
            defaultColorFilter = DrawableCompat.getColorFilter(getEditText().getBackground());
        return defaultColorFilter;
    }
}
_

見てわかるように、setErrorが呼び出された後、EditTextの背景をデフォルトの色にリセットしますが、メソッドdrawableStateChanged()でもリセットします。エラーも。

これが最良の解決策であるとは確信していませんが、これ以上の解決策が得られない場合は、当面解決済みとしてマークします。

33
MHogge

同じ問題がありました。検索してヒットして実行した後、私はこの問題を解決する簡単な方法を見つけました-

この最も簡単な方法を試してください-

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

そしてAndroid:background = "@ drawable/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>

これで、元の形状(@ drawable/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>

そして、元の形状(@ drawable/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. solid Android:color = "@ Android:color/transparent"-この単色のシェイプの色は透明になるため、エラーが発生した場合は透明になります。色。見てください-

**注-**必要に応じて、アイテムと無地のパディング値とトップ値を変更します(無地の線を削除することもできます)。

enter image description here

それだけです:-)ハッピーコーディング+1

8
Bajrang Hudda

受け入れられたソリューションを https://stackoverflow.com/a/40379564/291414 および https://stackoverflow.com/a/44744941/291414 で整理して、私は別のソリューションを書きましたクラス。 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
        ...
0
CoolMind