Google が CardView の背景色を動的に変更する方法を作成しないことにした理由はありますか?
ここで切り取った
回避策
@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);
}
};
ただし、このソリューションは新しい問題を引き起こします。pre-lollipop で何が起こるかはわかりませんが、CardView が最初に初期化されると、XML で設定した属性から背景として RoundRectDrawable が作成されるように見えます。上記のコードで色を変更すると、背景として MyRoundRectDrawableWithShadow が設定されます。その後、もう一度色を変更したい場合、card.getRadius()、card.getCardElevation() などは機能しなくなります。
したがって、これは最初に CardView から取得した背景を MyRoundRectDrawableWithShadow として解析しようとし、成功した場合はそこから値を取得します (2 回目以降は色を変更します)。ただし、失敗した場合 (背景が異なるクラスであるため、最初の色の変更になります)、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 でのみテストされています。