1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.support.v7.widget; 17 18import android.content.Context; 19import android.content.res.ColorStateList; 20import android.graphics.Canvas; 21import android.graphics.Paint; 22import android.graphics.Rect; 23import android.graphics.RectF; 24import android.support.annotation.Nullable; 25 26class CardViewBaseImpl implements CardViewImpl { 27 28 private final RectF mCornerRect = new RectF(); 29 30 @Override 31 public void initStatic() { 32 // Draws a round rect using 7 draw operations. This is faster than using 33 // canvas.drawRoundRect before JBMR1 because API 11-16 used alpha mask textures to draw 34 // shapes. 35 RoundRectDrawableWithShadow.sRoundRectHelper = 36 new RoundRectDrawableWithShadow.RoundRectHelper() { 37 @Override 38 public void drawRoundRect(Canvas canvas, RectF bounds, float cornerRadius, 39 Paint paint) { 40 final float twoRadius = cornerRadius * 2; 41 final float innerWidth = bounds.width() - twoRadius - 1; 42 final float innerHeight = bounds.height() - twoRadius - 1; 43 if (cornerRadius >= 1f) { 44 // increment corner radius to account for half pixels. 45 float roundedCornerRadius = cornerRadius + .5f; 46 mCornerRect.set(-roundedCornerRadius, -roundedCornerRadius, roundedCornerRadius, 47 roundedCornerRadius); 48 int saved = canvas.save(); 49 canvas.translate(bounds.left + roundedCornerRadius, 50 bounds.top + roundedCornerRadius); 51 canvas.drawArc(mCornerRect, 180, 90, true, paint); 52 canvas.translate(innerWidth, 0); 53 canvas.rotate(90); 54 canvas.drawArc(mCornerRect, 180, 90, true, paint); 55 canvas.translate(innerHeight, 0); 56 canvas.rotate(90); 57 canvas.drawArc(mCornerRect, 180, 90, true, paint); 58 canvas.translate(innerWidth, 0); 59 canvas.rotate(90); 60 canvas.drawArc(mCornerRect, 180, 90, true, paint); 61 canvas.restoreToCount(saved); 62 //draw top and bottom pieces 63 canvas.drawRect(bounds.left + roundedCornerRadius - 1f, bounds.top, 64 bounds.right - roundedCornerRadius + 1f, 65 bounds.top + roundedCornerRadius, paint); 66 67 canvas.drawRect(bounds.left + roundedCornerRadius - 1f, 68 bounds.bottom - roundedCornerRadius, 69 bounds.right - roundedCornerRadius + 1f, bounds.bottom, paint); 70 } 71 // center 72 canvas.drawRect(bounds.left, bounds.top + cornerRadius, 73 bounds.right, bounds.bottom - cornerRadius , paint); 74 } 75 }; 76 } 77 78 @Override 79 public void initialize(CardViewDelegate cardView, Context context, 80 ColorStateList backgroundColor, float radius, float elevation, float maxElevation) { 81 RoundRectDrawableWithShadow background = createBackground(context, backgroundColor, radius, 82 elevation, maxElevation); 83 background.setAddPaddingForCorners(cardView.getPreventCornerOverlap()); 84 cardView.setCardBackground(background); 85 updatePadding(cardView); 86 } 87 88 private RoundRectDrawableWithShadow createBackground(Context context, 89 ColorStateList backgroundColor, float radius, float elevation, 90 float maxElevation) { 91 return new RoundRectDrawableWithShadow(context.getResources(), backgroundColor, radius, 92 elevation, maxElevation); 93 } 94 95 @Override 96 public void updatePadding(CardViewDelegate cardView) { 97 Rect shadowPadding = new Rect(); 98 getShadowBackground(cardView).getMaxShadowAndCornerPadding(shadowPadding); 99 cardView.setMinWidthHeightInternal((int) Math.ceil(getMinWidth(cardView)), 100 (int) Math.ceil(getMinHeight(cardView))); 101 cardView.setShadowPadding(shadowPadding.left, shadowPadding.top, 102 shadowPadding.right, shadowPadding.bottom); 103 } 104 105 @Override 106 public void onCompatPaddingChanged(CardViewDelegate cardView) { 107 // NO OP 108 } 109 110 @Override 111 public void onPreventCornerOverlapChanged(CardViewDelegate cardView) { 112 getShadowBackground(cardView).setAddPaddingForCorners(cardView.getPreventCornerOverlap()); 113 updatePadding(cardView); 114 } 115 116 @Override 117 public void setBackgroundColor(CardViewDelegate cardView, @Nullable ColorStateList color) { 118 getShadowBackground(cardView).setColor(color); 119 } 120 121 @Override 122 public ColorStateList getBackgroundColor(CardViewDelegate cardView) { 123 return getShadowBackground(cardView).getColor(); 124 } 125 126 @Override 127 public void setRadius(CardViewDelegate cardView, float radius) { 128 getShadowBackground(cardView).setCornerRadius(radius); 129 updatePadding(cardView); 130 } 131 132 @Override 133 public float getRadius(CardViewDelegate cardView) { 134 return getShadowBackground(cardView).getCornerRadius(); 135 } 136 137 @Override 138 public void setElevation(CardViewDelegate cardView, float elevation) { 139 getShadowBackground(cardView).setShadowSize(elevation); 140 } 141 142 @Override 143 public float getElevation(CardViewDelegate cardView) { 144 return getShadowBackground(cardView).getShadowSize(); 145 } 146 147 @Override 148 public void setMaxElevation(CardViewDelegate cardView, float maxElevation) { 149 getShadowBackground(cardView).setMaxShadowSize(maxElevation); 150 updatePadding(cardView); 151 } 152 153 @Override 154 public float getMaxElevation(CardViewDelegate cardView) { 155 return getShadowBackground(cardView).getMaxShadowSize(); 156 } 157 158 @Override 159 public float getMinWidth(CardViewDelegate cardView) { 160 return getShadowBackground(cardView).getMinWidth(); 161 } 162 163 @Override 164 public float getMinHeight(CardViewDelegate cardView) { 165 return getShadowBackground(cardView).getMinHeight(); 166 } 167 168 private RoundRectDrawableWithShadow getShadowBackground(CardViewDelegate cardView) { 169 return ((RoundRectDrawableWithShadow) cardView.getCardBackground()); 170 } 171} 172