Google 决定不制定动态更改 CardView 的背景颜色的方法是否有原因?
剪在这里
解决方法
@Justin Powell 建议的简单代码行对我不起作用。在 Android 5.0 上就是这样。但它确实让我朝着正确的方向前进。
这段代码,(MyRoundRectDrawableWithShadow 是这个的副本)
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)
这只是说有一个接口被调用,它是空的。然后我查看了CardView 源代码,了解它是如何做到的。我发现下面这段代码以某种静态方式初始化界面(我不太明白为什么,如果你知道,请解释一下),然后我在类init中调用一次,然后你可以设置颜色的卡片使用上面的代码块。
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));
希望这是有道理的,我不是以英语为母语的人......如前所述,这仅在 Lollipop 上进行了测试。