title: How to change background color of CardView programmatically
body: <p>Is there a reason why Google decided not to make a method to dynamically change the background color of a CardView? </p>
  
  <p>Snipped <a href="https://developer.android.com/reference/android/support/v7/widget/CardView.html" rel="nofollow noreferrer">here</a>
  <img src="https://i.stack.imgur.com/oQGsh.jpg" alt="enter image description here"></p>
  
  <hr>
  
  <p><strong>WORKAROUND</strong></p>
  
  <p>The simple line of code @Justin Powell suggested does not work for me. On Android 5.0 that is. But it did get me in the right direction.</p>
  
  <p>This code, (MyRoundRectDrawableWithShadow being a copy of <a href="https://android.googlesource.com/platform/frameworks/support/+/lollipop-release/v7/cardview/eclair-mr1/android/support/v7/widget/RoundRectDrawableWithShadow.java" rel="nofollow noreferrer">this</a>)</p>
  
  <pre><code>        card.setBackgroundDrawable(new MyRoundRectDrawableWithShadow(context.getResources(),
                  color,
                  card.getRadius(),
                  card.getCardElevation(),
                  card.getMaxCardElevation()));
  </code></pre>
  
  <p>... gave me this error,</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>Which simply says that there is an Interface getting called that is null. I then checked out the <a href="https://android.googlesource.com/platform/frameworks/support/+/lollipop-release/v7/cardview/eclair-mr1/android/support/v7/widget/CardViewEclairMr1.java" rel="nofollow noreferrer">CardView source</a>, to find out how it did it. I found that the following piece of code initializes the interface in some static way (I don't really understand why, please explain if you know), which I then call once at class init, and you can then set the card of the color with the above chunk of code.</p>
  
  <pre><code>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);
              }
          };
  </code></pre>
  
  <p>This solution does however spawn a new problem. Not sure what happens on pre-lollipop, but when the CardView is first initialized it appears to create a RoundRectDrawable as the background from the attributes you've set in XML. When we then change the color with the above code, we set a MyRoundRectDrawableWithShadow as the background, and if you then want to change the color once again, the card.getRadius(), card.getCardElevation() etc, will no longer work.</p>
  
  <p>This therefore first tries to parse the background it gets from the CardView as a MyRoundRectDrawableWithShadow from which it then gets the values if it succeeds (which it will the second+ time you change the color). But, if it fails (which is will on the first color change, because the background is a different class) it will get the values directly from the CardView itself.</p>
  
  <pre><code>    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));
  </code></pre>
  
  <p>Hope that made sense, I'm not a native English speaker... As mentioned, this was only tested on Lollipop.</p>