决定尝试新的DrawableCompat
课程。按照reliable source的说明,我来电:
Button b = (Button) findViewById(R.id.button);
Drawable d = b.getBackground();
d = DrawableCompat.wrap(d);
DrawableCompat.setTintList(d, getResources().getColorStateList(...));
令人惊讶的是,这个不起作用:我的按钮背景获得了我为未按下的非聚焦状态定义的颜色,但它在按下/开焦时没有变化。
我能够以完全不同的方式取得成功,
Button b = (Button) findViewById(R.id.button);
AppCompatButton b2 = (AppCompatButton) b; //direct casting to AppCompatButton throws annoying warning
b2.setSupportBackgroundTintList(getResources().getColorStateList(...));
哪个工作并且更紧凑,但是我想改用DrawableCompat
。你能告诉我为什么会这样吗?
答案 0 :(得分:4)
d = DrawableCompat.wrap(d);
如果新实例尚未DrawableWrapper
,则会创建一个新实例,因此您对此新实例进行着色,但存储在按钮中的原始实例保持不变。
整个代码看起来像这样
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
tints iself 而不是Lollipop本机不可绘制(但前提是背景位于白名单上,例如默认appcompat按钮drawable)。所以你必须先从按钮本身清除色调。
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
编辑2:
当您尝试重置按钮的色调列表时,上面的代码将抛出NullPointerException
。我目前正在提交错误报告。
与此同时,我建议您直接或使用@null
背景以及通过
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();
因此,所有这些看起来非常难看,现在最简单的(也是唯一有效且简单但又隐蔽的)解决方案是:
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);
}
你应该把这个怪物放在一个实用程序类中。