使用DrawableCompat类应用tintList [英] Using DrawableCompat class to apply a tintList

查看:169
本文介绍了使用DrawableCompat类应用tintList的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

决定尝试新的DrawableCompat类.按照可靠来源中的说明,我正在打电话:

Decided to try the new DrawableCompat class. Following instructions from a reliable source, I'm calling:

Button b = (Button) findViewById(R.id.button);
Drawable d = b.getBackground();
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, getResources().getColorStateList(...));

令人惊讶的是,这不起作用:我的按钮背景使用我为未按下,未聚焦状态定义的颜色,但是在按下/聚焦时不会改变.

Surprisingly, this does not work: my button background gets the color I define for the un-pressed, un-focused state, but it doesn't change on press / on focus.

我能够以完全不同的方式取得成功,

I was able to succeed in a totally different way,

Button b = (Button) findViewById(R.id.button);
AppCompatButton b2 = (AppCompatButton) b; //direct casting to AppCompatButton throws annoying warning
b2.setSupportBackgroundTintList(getResources().getColorStateList(...));

有效,并且更加紧凑,但是我想改用DrawableCompat.你能告诉我为什么吗?

which works and is even more compact, but however I wanted to use DrawableCompat instead. Could you tell me why is it?

推荐答案

d = DrawableCompat.wrap(d);创建一个新实例(如果尚未创建),因此您可以为该新实例着色,但存储在按钮中的原始实例保持不变.

d = DrawableCompat.wrap(d); creates a new instance if it's not already DrawableWrapper so you tint this new instance but the original which is stored in the button remains the same.

整个代码看起来像这样

Button b = (Button) findViewById(R.id.button);
Drawable d = b.getBackground();
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, getResources().getColorStateList(...));
b.setBackground(d); // or setBackgroundDrawable on older platforms

是的,我会采用您所描述的第二种方法,因为它从您身上提取了辛苦的工作.

只是深入研究appcompat代码,发现AppCompatButton会着色 iself 而不是可绘制对象,而不像Lollipop原生(但仅当背景在白名单上,例如默认的appcompat按钮可绘制对象) ).因此,您必须首先清除按钮本身的色调.

Just took a dive into appcompat code and found out that the AppCompatButton tints iself and not the drawable unlike Lollipop native (but only if the background is on the whitelist, e.g. default appcompat button drawable). So you have to clear tint from the button itself first.

Button b = (Button) findViewById(R.id.button);

if (b instanceof AppCompatButton) {
    ((AppCompatButton)b).setSupportBackgroundTintList(null);
}

Drawable d = b.getBackground();
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, getResources().getColorStateList(...));
b.setBackground(d); // or setBackgroundDrawable on older platforms

当您尝试重置按钮的色调列表时,上面的代码将引发NullPointerException.我目前正在提交错误报告.

The above code will throw a NullPointerException when you try to reset the button's tint list. I'm currently filing a bug report.

同时,我建议您直接使用自定义背景(不通过appcompat着色将其列入白名单)或使用@null背景来为按钮充气,并通过解析默认按钮背景来

In the meantime I suggest you inflate the button with a custom background (non-whitelisted for tinting by appcompat) directly or with @null background and resolving the default button background by

TypedArray ta = context.obtainStyledAttributes(null, new int[]{android.R.attr.background}, R.attr.buttonStyle, R.style.Widget_AppCompat_Button);
Drawable d = ta.getDrawable(0);
ta.recycle();

因此,尽管这一切看起来都很丑陋,但现在对您来说,最简单的解决方案是:

So as all this looks pretty fugly, the easiest (and only working and foolproof, yet hidious as well) solution for you now is this:

Button b = (Button) findViewById(R.id.button);
ColorStateList c = getResources().getColorStateList(...);
Drawable d = b.getBackground();
if (b instanceof AppCompatButton) {
    // appcompat button replaces tint of its drawable background
    ((AppCompatButton)b).setSupportBackgroundTintList(c);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Lollipop button replaces tint of its drawable background
    // however it is not equal to d.setTintList(c)
    b.setBackgroundTintList(c);
} else {
    // this should only happen if 
    // * manually creating a Button instead of AppCompatButton
    // * LayoutInflater did not translate a Button to AppCompatButton
    d = DrawableCompat.wrap(d);
    DrawableCompat.setTintList(d, c);
    b.setBackgroundDrawable(d);
}

您应该将这种怪异放在实用程序类中.

You should put this monstrosity away in a utility class.

这篇关于使用DrawableCompat类应用tintList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆