以编程方式更改Android EditText的色调颜色

33
我正在尝试在运行时编程方式下更改EditText视图的色调颜色。基本上,我想更改通常应用为?attr/colorControlNormal的东西,例如在默认背景可绘制项中。
仅通过设置一个带有一种颜色的新ColorsStateList来更改背景色调不会正确应用: editText.setBackgroundTintList(ColorStateList.valueOf(color)); 首先,结果适用于所有EditText,尽管已应用色调列表并且在内部变异可绘制项。 此外,默认背景1中指定的alpha在开始时是可见的。
这是仅在第一个EditText上设置色调颜色的结果: outcome of setting the tint color on just the first EditText 所以我的问题是:如何在编程方式下正确应用色调到EditText
6个回答

47

如果您只想临时更改单个 EditText 的颜色(例如标记错误),您还需要调用 mutate()(因此:editText.getBackground().mutate()....)。否则,颜色更改将在多个 EditTexts 之间共享,并且重置(首先保存旧的 Background)会使旧颜色和新颜色以奇怪的方式混合。 - Neph

24

通过新引入的 android.support.v4.graphics.drawable.DrawableCompat#setTint 方法,现在可以设置颜色。


1
请给我一个例子。 - Lucas B.
9
示例:DrawableCompat.setTint(editText.getBackground(), ContextCompat.getColor(context, R.color.xxx)); - Wess
你如何使用代码将背景颜色重置为默认值?如果我再次使用相同的代码,但是使用原始颜色(例如ColorAccent),即使文本字段处于非活动状态(通常应该是灰色的),它也会使用该颜色。如果我调用editText.setBackground(oldBackground),则EditText在非活动状态下使用旧颜色,在活动状态下使用新颜色,因此两者之间混合。 - Neph

14
尝试创建自定义的EditText,并在构造函数中添加this.setBackgroundTintList( ColorStateList.valueOf( color ) );

1
在创建时更改色调对我的用例来说是不够的。我需要在运行时动态更改它。 - Moritz
因此,您可以在自定义的EditText中创建一个监听器,并在需要时调用此方法。 - Lennon Spirlandelli
每次更改颜色都会创建一个新的视图,这也需要移植TextView当前具有的所有状态。听起来像是很多额外的开销。 - Moritz
不,那样不会创建一个新的视图。你必须创建一个带有监听器的自定义EditText来改变它自己的颜色。之后,当你想要改变颜色时,只需调用监听器,每个单独的EditText都会响应这个监听器。 - Lennon Spirlandelli
我不明白你的思路。当你在构造函数中指定设置某些内容时,唯一再次调用此代码的方法是通过实例化。 - Moritz
是的,我说过那句话。但你说EditText在创建时会改变它们的颜色。因此,我告诉你要创建一个监听器,但监听器不能在构造函数中创建。在这种情况下,你必须像通常的方法一样在类中创建它。 - Lennon Spirlandelli

6

setColorFilter 对我不起作用。 我使用了以下代码:

Drawable wrappedDrawable = DrawableCompat.wrap(mView.getBackground());
DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.red));
mView.setBackgroundDrawable(wrappedDrawable);

或者

DrawableCompat.setTint(mView.getBackground(), ContextCompat.getColor(this, R.color.red));

让我们来试试。


2

针对Kotlin

editText.backgroundTintList = ColorStateList.valueOf(R.color.colorLightGray )

-3

我编写了一个小组件来实现这个行为。

几个重要的注意事项:

  • 使用了旧版的setColorFilter方法
  • 为了使色调生效,首先将焦点切换到其他视图,然后对EditText背景可绘制进行着色

用法

ErrorLabelLayout layoutPassError = (ErrorLabelLayout) findViewById(R.id.layoutPasswordError)
layoutPassError.setError("Password_is_wrong");
// when you want to clear error e.g. in on text changed method
layoutPassError.clearError();

XML

<com.view.material.ErrorLabelLayout
    android:id="@+id/layoutPasswordError"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:focusable="false">

    <EditText
        android:id="@+id/editPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword"
        android:hint="Enter your password"/>
</com.view.material.ErrorLabelLayout>

源代码

public class ErrorLabelLayout extends LinearLayout implements ViewGroup.OnHierarchyChangeListener {

    private static final int ERROR_LABEL_TEXT_SIZE = 12;
    private static final int ERROR_LABEL_PADDING = 4;

    private TextView mErrorLabel;
    private Drawable mDrawable;
    private int mErrorColor;

    public ErrorLabelLayout(Context context) {
        super(context);
        initView();
    }

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

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

    private void initView() {
        setOnHierarchyChangeListener(this);
        setOrientation(VERTICAL);
        mErrorColor = Color.parseColor("#D32F2F");
        initErrorLabel();
    }

    private void initErrorLabel() {
        mErrorLabel = new TextView(getContext());
        mErrorLabel.setFocusable(true);
        mErrorLabel.setFocusableInTouchMode(true);
        mErrorLabel.setTextSize(ERROR_LABEL_TEXT_SIZE);
        mErrorLabel.setTextColor(mErrorColor);
        mErrorLabel.setPadding(dipsToPix(ERROR_LABEL_PADDING), 0, dipsToPix(ERROR_LABEL_PADDING), 0);
    }

    public void setErrorColor(int color) {
        mErrorColor = color;
        mErrorLabel.setTextColor(mErrorColor);
    }

    public void clearError() {
        mErrorLabel.setVisibility(INVISIBLE);
        mDrawable.clearColorFilter();
    }

    public void setError(String text) {
        mErrorLabel.setVisibility(VISIBLE);
        mErrorLabel.setText(text);
        // changing focus from EditText to error label, necessary for Android L only
        // EditText background Drawable is not tinted, until EditText remains focus
        mErrorLabel.requestFocus();
        // tint drawable
        mDrawable.setColorFilter(mErrorColor, PorterDuff.Mode.SRC_ATOP);
    }

    @Override
    public void onChildViewAdded(View parent, View child) {
        int childCount = getChildCount();
        if (childCount == 1) {
            mDrawable = getChildAt(0).getBackground();
            addView(mErrorLabel);
        }
    }

    @Override
    public void onChildViewRemoved(View parent, View child) {
    }

    private int dipsToPix(float dps) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                dps, getResources().getDisplayMetrics());
    }
}

使用 com.android.support:appcompat-v7:22.1.1 库在 API 16 / 21 上进行了测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接