DrawableCompat 着色不适用于 Lollipop 之前的版本

DrawableCompat tinting does not work on pre-Lollipop

我正在使用新的 TextInputLayout 来包装 EditText。当我确定某个字段有错误时,我会执行以下操作:

Drawable drawable = DrawableCompat.wrap(getEditText().getBackground());

DrawableCompat.setTintList(drawable, ColorStateList.valueOf(Color.RED));

这适用于 5.0 并将下划线变为红色,但在 4.4 或 4.1 测试设备上不执行任何操作。我在这里错过了什么?看起来很简单,根据 google "just works"...很确定我也有它的最新版本:

编译'com.android.support:design:22.2.0'

FWIW,如果我使用 setColorFilter 而不是 setTint 那么它可以在所有平台上运行,但是我遇到了问题,它会消失并且不会在焦点是 set/left/etc 时立即返回...我会更喜欢用色调来做(如果有人正在寻找额外的信用大声笑,真的更喜欢将色调应用于焦点和非焦点状态)

谢谢!

当您调用 wrap() 时,原始 Drawable 会在内部包装成新的 DrawableWrapper,用于在旧设备上实现着色。因此,要使其正常工作,您必须将返回的 Drawable 设置回 EditText:

final Drawable originalDrawable = editText.getBackground();
final Drawable wrappedDrawable = DrawableCompat.wrap(originalDrawable);
DrawableCompat.setTintList(wrappedDrawable, ColorStateList.valueOf(Color.RED));
editText.setBackground(wrappedDrawable);

从支持库的版本 23.2.0 开始,您还可以使用 setTint() 而不是 setTintList() 来设置一种色调,而无需创建 ColorStateList.

DrawableCompat.setTint(wrappedDrawable, Color.RED);

如果您想确保 API 级别 16 之后的向后兼容性,您 运行 会遇到一些小麻烦。 setBackground() 是在 API 级别 16 中添加的,您需要在此之前在设备上调用 setBackgroundDrawable()。最好实现一个帮助你的方法:

public static void setBackground(View view, Drawable background) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        view.setBackground(background);
    } else {
        view.setBackgroundDrawable(background);
    }
}