Google是否决定不采用一种方法来动态更改CardView的背景颜色?
已抓取here
WORKAROUND
@ Justin Powell建议的简单代码行对我不起作用。在Android 5.0上是这样。但这确实使我朝着正确的方向前进。
此代码,(MyRoundRectDrawableWithShadow是this的副本]
card.setBackgroundDrawable(new MyRoundRectDrawableWithShadow(context.getResources(),
color,
card.getRadius(),
card.getCardElevation(),
card.getMaxCardElevation()));
...给了我这个错误,
java.lang.NullPointerException: Attempt to invoke interface method 'void com.example.app.MyRoundRectDrawableWithShadow$RoundRectHelper.drawRoundRect(android.graphics.Canvas, android.graphics.RectF, float, android.graphics.Paint)' on a null object reference
at com.example.app.MyRoundRectDrawableWithShadow.draw(MyRoundRectDrawableWithShadow.java:172)
只是简单地说,有一个接口被调用为null。然后,我检查了CardView source,以了解其效果。我发现以下代码以某种静态方式初始化了接口(我不太明白为什么,请解释一下),然后在类初始化时调用一次,然后可以设置颜色卡上面的代码块。
final RectF sCornerRect = new RectF();
MyRoundRectDrawableWithShadow.sRoundRectHelper
= new MyRoundRectDrawableWithShadow.RoundRectHelper() {
@Override
public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius,
Paint paint) {
final float twoRadius = cornerRadius * 2;
final float innerWidth = bounds.width() - twoRadius;
final float innerHeight = bounds.height() - twoRadius;
sCornerRect.set(bounds.left, bounds.top,
bounds.left + cornerRadius * 2, bounds.top + cornerRadius * 2);
canvas.drawArc(sCornerRect, 180, 90, true, paint);
sCornerRect.offset(innerWidth, 0);
canvas.drawArc(sCornerRect, 270, 90, true, paint);
sCornerRect.offset(0, innerHeight);
canvas.drawArc(sCornerRect, 0, 90, true, paint);
sCornerRect.offset(-innerWidth, 0);
canvas.drawArc(sCornerRect, 90, 90, true, paint);
//draw top and bottom pieces
canvas.drawRect(bounds.left + cornerRadius, bounds.top,
bounds.right - cornerRadius, bounds.top + cornerRadius,
paint);
canvas.drawRect(bounds.left + cornerRadius,
bounds.bottom - cornerRadius, bounds.right - cornerRadius,
bounds.bottom, paint);
//center
canvas.drawRect(bounds.left, bounds.top + cornerRadius,
bounds.right, bounds.bottom - cornerRadius, paint);
}
};
但是,此解决方案确实产生了一个新问题。不确定棒棒糖之前会发生什么,但是当CardView首次初始化时,它似乎会根据您在XML中设置的属性创建一个RoundRectDrawable作为背景。然后,当我们使用上述代码更改颜色时,我们将MyRoundRectDrawableWithShadow设置为背景,如果您想再次更改颜色,则card.getRadius(),card.getCardElevation()等将不再起作用。
因此,它首先尝试将从CardView中获取的背景解析为MyRoundRectDrawableWithShadow,如果成功,它将从中获取值(第二次或更多次更改颜色)。但是,如果失败(由于背景是不同的类,这将是第一个颜色更改的结果),它将直接从CardView本身获取值。
float cardRadius;
float maxCardElevation;
try{
MyRoundRectDrawableWithShadow background = (MyRoundRectDrawableWithShadow)card.getBackground();
cardRadius = background.getCornerRadius();
maxCardElevation = background.getMaxShadowSize();
}catch (ClassCastException classCastExeption){
cardRadius = card.getRadius();
maxCardElevation = card.getMaxCardElevation();
}
card.setBackgroundDrawable(
new MyRoundRectDrawableWithShadow(context.getResources(),
Color.parseColor(note.getColor()),
cardRadius,
card.getCardElevation(),
maxCardElevation));
希望这很有道理,我不是英语为母语的人……如上所述,这仅在棒棒糖上进行了测试。
我不知道任何特定的理由。
但是,如果您有兴趣绕过此遗漏...
CardView使用此属性所做的所有事情都是使用颜色创建一个可绘制的圆角矩形,然后将其分配为CardView的背景。如果您确实要以编程方式设置颜色,则可以创建RoundRectDrawableWithShadow的副本,然后执行以下操作:
mCardView.setBackgroundDrawable(new MyRoundRectDrawableWithShadow(getResources(), color, radius));
您不能继承RoundRectDrawableWithShadow的子类,或者因为它不是公共的而直接使用它。
只需更新:最新的支持库提供了直接功能:
CardView cardView;
cardView.setCardBackgroundColor(color);
这很棘手。您需要修改API才能完成此功能。 @Justin Powell's answer是正确的,但是在API 21中崩溃。我的解决方案解决了这个问题。您需要添加这两个类:
MyRoundRectDrawableWithShadow
:
package android.support.v7.widget;
import android.content.res.Resources;
public class MyRoundRectDrawableWithShadow extends RoundRectDrawableWithShadow {
public MyRoundRectDrawableWithShadow(Resources resources, int backgroundColor) {
super(resources, backgroundColor,
resources.getDimensionPixelSize(R.dimen.cardview_default_radius),
resources.getDimensionPixelSize(R.dimen.cardview_default_elevation),
resources.getDimensionPixelSize(R.dimen.cardview_default_elevation));
}
public MyRoundRectDrawableWithShadow(Resources resources, int backgroundColor, float radius) {
super(resources, backgroundColor, radius,
resources.getDimensionPixelSize(R.dimen.cardview_default_elevation),
resources.getDimensionPixelSize(R.dimen.cardview_default_elevation));
}
public MyRoundRectDrawableWithShadow(Resources resources, int backgroundColor, float radius,
float shadowSize, float maxShadowSize) {
super(resources, backgroundColor, radius, shadowSize, maxShadowSize);
}
}
MyRoundRectDrawable
:
package android.support.v7.widget;
import android.content.res.Resources;
public class MyRoundRectDrawable extends RoundRectDrawable {
public MyRoundRectDrawable(Resources resources, int backgroundColor) {
super(backgroundColor, resources.getDimensionPixelSize(R.dimen.cardview_default_radius));
}
public MyRoundRectDrawable(int backgroundColor, float radius) {
super(backgroundColor, radius);
}
}
然后使用此代码更改背景色:
final Drawable background;
if (Build.VERSION.SDK_INT >= 21) {
background = new MyRoundRectDrawable(color);
} else {
background = new MyRoundRectDrawableWithShadow(resources, color);
}
// This is to avoid to use a deprecated method
if (Build.VERSION.SDK_INT >= 16) {
cardView.setBackground(background);
} else {
cardView.setBackgroundDrawable(background);
}
只需编写以下代码段:cardView.setCardBackgroundColor(getResources().getColor(R.color.colorPrimary));
您想要的代码