183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar/*
283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * Copyright (C) 2014 The Android Open Source Project
383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar *
483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * you may not use this file except in compliance with the License.
683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * You may obtain a copy of the License at
783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar *
883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar *
1083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * Unless required by applicable law or agreed to in writing, software
1183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
1283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * See the License for the specific language governing permissions and
1483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * limitations under the License.
1583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar */
1683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
1783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarpackage android.support.v7.widget;
1883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
1983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.content.Context;
2083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.content.res.TypedArray;
2118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyarimport android.graphics.Rect;
2283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.os.Build;
2383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.support.v7.cardview.R;
2483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.util.AttributeSet;
2583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarimport android.widget.FrameLayout;
2683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
2783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar/**
2818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * A FrameLayout with a rounded corner background and shadow.
2983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * <p>
3083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * CardView uses <code>elevation</code> property on L for shadows and falls back to a custom shadow
3183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * implementation on older platforms.
3283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * <p>
3318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * Due to expensive nature of rounded corner clipping, on platforms before L, CardView does not
3418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * clip its children that intersect with rounded corners. Instead, it adds padding to avoid such
35c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar * intersection (See {@link #setPreventCornerOverlap(boolean)} to change this behavior).
3618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * <p>
3718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * Before L, CardView adds padding to its content and draws shadows to that area. This padding
38bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * amount is equal to <code>maxCardElevation + (1 - cos45) * cornerRadius</code> on the sides and
39bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * <code>maxCardElevation * 1.5 + (1 - cos45) * cornerRadius</code> on top and bottom.
40bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * <p>
41c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar * Since padding is used to offset content for shadows, you cannot set padding on CardView.
42c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar * Instead,
43bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * you can use content padding attributes in XML or {@link #setContentPadding(int, int, int, int)}
44bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * in code to set the padding between the edges of the Card and children of CardView.
45bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * <p>
46bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * Note that, if you specify exact dimensions for the CardView, because of the shadows, its content
47bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * area will be different between platforms before L and after L. By using api version specific
48bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * resource values, you can avoid these changes. Alternatively, If you want CardView to add inner
49bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * padding on platforms L and after as well, you can set {@link #setUseCompatPadding(boolean)} to
50bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * <code>true</code>.
5118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * <p>
5218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * To change CardView's elevation in a backward compatible way, use
5318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * {@link #setCardElevation(float)}. CardView will use elevation API on L and before L, it will
5418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * change the shadow size. To avoid moving the View while shadow size is changing, shadow size is
5518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * clamped by {@link #getMaxCardElevation()}. If you want to change elevation dynamically, you
5618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * should call {@link #setMaxCardElevation(float)} when CardView is initialized.
5783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar *
5883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardBackgroundColor
59bc943f7fa746c149c5e4c3a4eed7febe494d5df5Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardCornerRadius
6018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
6118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardMaxElevation
62bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardUseCompatPadding
63c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_cardPreventCornerOverlap
64bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPadding
65bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingLeft
66bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingTop
67bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingRight
68bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingBottom
6983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar */
7083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyarpublic class CardView extends FrameLayout implements CardViewDelegate {
7183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
72bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    private static final CardViewImpl IMPL;
7318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
7483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    static {
75a52784195525cdb1f2bb4d8dde1b8b314f480957Chet Haase        if (Build.VERSION.SDK_INT >= 21) {
7683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar            IMPL = new CardViewApi21();
7783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        } else if (Build.VERSION.SDK_INT >= 17) {
7883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar            IMPL = new CardViewJellybeanMr1();
7983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        } else {
8083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar            IMPL = new CardViewEclairMr1();
8183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        }
8283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        IMPL.initStatic();
8383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
8483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
85bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    private boolean mCompatPadding;
86bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
87c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    private boolean mPreventCornerOverlap;
88c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar
89bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    private final Rect mContentPadding = new Rect();
90bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
91bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    private final Rect mShadowBounds = new Rect();
92bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
93bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
9483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    public CardView(Context context) {
9583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        super(context);
9683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        initialize(context, null, 0);
9783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
9883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
9983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    public CardView(Context context, AttributeSet attrs) {
10083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        super(context, attrs);
10183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        initialize(context, attrs, 0);
10283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
10383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
10483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    public CardView(Context context, AttributeSet attrs, int defStyleAttr) {
10583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        super(context, attrs, defStyleAttr);
10683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        initialize(context, attrs, defStyleAttr);
10783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
10883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
109bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    @Override
110bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public void setPadding(int left, int top, int right, int bottom) {
111bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        // NO OP
112bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
113bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
114bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public void setPaddingRelative(int start, int top, int end, int bottom) {
115bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        // NO OP
116bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
117bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
118bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
119bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Returns whether CardView will add inner padding on platforms L and after.
120bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
121bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @return True CardView adds inner padding on platforms L and after to have same dimensions
122bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * with platforms before L.
123bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
124c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    @Override
125bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public boolean getUseCompatPadding() {
126bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        return mCompatPadding;
127bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
128bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
129bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
130bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * CardView adds additional padding to draw shadows on platforms before L.
131bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * <p>
132bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * This may cause Cards to have different sizes between L and before L. If you need to align
133bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * CardView with other Views, you may need api version specific dimension resources to account
134bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * for the changes.
135bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * As an alternative, you can set this flag to <code>true</code> and CardView will add the same
136bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * padding values on platforms L and after.
137bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * <p>
138bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Since setting this flag to true adds unnecessary gaps in the UI, default value is
139bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * <code>false</code>.
140bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
141bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @param useCompatPadding True if CardView should add padding for the shadows on platforms L
142bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *                         and above.
143c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardUseCompatPadding
144bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
145bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public void setUseCompatPadding(boolean useCompatPadding) {
146bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        if (mCompatPadding == useCompatPadding) {
147bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar            return;
148bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        }
149bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mCompatPadding = useCompatPadding;
150bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        IMPL.onCompatPaddingChanged(this);
151bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
152bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
153bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
154bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Sets the padding between the Card's edges and the children of CardView.
155bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * <p>
156bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Depending on platform version or {@link #getUseCompatPadding()} settings, CardView may
157bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * update these values before calling {@link android.view.View#setPadding(int, int, int, int)}.
158bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
159c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @param left   The left padding in pixels
160c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @param top    The top padding in pixels
161c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @param right  The right padding in pixels
162c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @param bottom The bottom padding in pixels
163bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPadding
164bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingLeft
165bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingTop
166bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingRight
167bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_contentPaddingBottom
168bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
169bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public void setContentPadding(int left, int top, int right, int bottom) {
170bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mContentPadding.set(left, top, right, bottom);
171bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        IMPL.updatePadding(this);
172bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
17318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
17418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    @Override
17518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        if (IMPL instanceof CardViewApi21 == false) {
17718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
17818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            switch (widthMode) {
17918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                case MeasureSpec.EXACTLY:
18018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                case MeasureSpec.AT_MOST:
18118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    final int minWidth = (int) Math.ceil(IMPL.getMinWidth(this));
18218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minWidth,
18318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                            MeasureSpec.getSize(widthMeasureSpec)), widthMode);
18418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    break;
18518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            }
18618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
18718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
18818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            switch (heightMode) {
18918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                case MeasureSpec.EXACTLY:
19018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                case MeasureSpec.AT_MOST:
19118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    final int minHeight = (int) Math.ceil(IMPL.getMinHeight(this));
19218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minHeight,
19318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                            MeasureSpec.getSize(heightMeasureSpec)), heightMode);
19418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar                    break;
19518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            }
19618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
19718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        } else {
19818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
19918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        }
20018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    }
20118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
20283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    private void initialize(Context context, AttributeSet attrs, int defStyleAttr) {
20383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CardView, defStyleAttr,
204bc943f7fa746c149c5e4c3a4eed7febe494d5df5Yigit Boyar                R.style.CardView_Light);
20583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        int backgroundColor = a.getColor(R.styleable.CardView_cardBackgroundColor, 0);
20683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        float radius = a.getDimension(R.styleable.CardView_cardCornerRadius, 0);
20718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        float elevation = a.getDimension(R.styleable.CardView_cardElevation, 0);
20818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        float maxElevation = a.getDimension(R.styleable.CardView_cardMaxElevation, 0);
209bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mCompatPadding = a.getBoolean(R.styleable.CardView_cardUseCompatPadding, false);
210c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        mPreventCornerOverlap = a.getBoolean(R.styleable.CardView_cardPreventCornerOverlap, true);
211bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        int defaultPadding = a.getDimensionPixelSize(R.styleable.CardView_contentPadding, 0);
212bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mContentPadding.left = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingLeft,
213bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar                defaultPadding);
214bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mContentPadding.top = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingTop,
215bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar                defaultPadding);
216bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mContentPadding.right = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingRight,
217bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar                defaultPadding);
218bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mContentPadding.bottom = a.getDimensionPixelSize(R.styleable.CardView_contentPaddingBottom,
219bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar                defaultPadding);
22018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        if (elevation > maxElevation) {
22118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar            maxElevation = elevation;
22218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        }
22383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        a.recycle();
22418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        IMPL.initialize(this, context, backgroundColor, radius, elevation, maxElevation);
22583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
22683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
22783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    /**
2284eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar     * Updates the background color of the CardView
2294eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar     *
2304eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar     * @param color The new color to set for the card background
2314eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardBackgroundColor
2324eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar     */
2334eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar    public void setCardBackgroundColor(int color) {
2344eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar        IMPL.setBackgroundColor(this, color);
2354eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar    }
2364eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar
2374eb77f0ed24a9d300f7d12959de8cf7efd837e2fYigit Boyar    /**
238bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Returns the inner padding after the Card's left edge
239bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
240bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @return the inner padding after the Card's left edge
241bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
242bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public int getContentPaddingLeft() {
243bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        return mContentPadding.left;
244bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
245bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
246bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
247bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Returns the inner padding before the Card's right edge
248bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
249bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @return the inner padding before the Card's right edge
250bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
251bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public int getContentPaddingRight() {
252bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        return mContentPadding.right;
253bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
254bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
255bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
256bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Returns the inner padding after the Card's top edge
257bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
258bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @return the inner padding after the Card's top edge
259bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
260bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public int getContentPaddingTop() {
261bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        return mContentPadding.top;
262bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
263bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
264bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
265bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Returns the inner padding before the Card's bottom edge
266bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     *
267bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @return the inner padding before the Card's bottom edge
268bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
269bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public int getContentPaddingBottom() {
270bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        return mContentPadding.bottom;
271bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
272bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
273bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
27483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * Updates the corner radius of the CardView.
27583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     *
27683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * @param radius The radius in pixels of the corners of the rectangle shape
277bc943f7fa746c149c5e4c3a4eed7febe494d5df5Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardCornerRadius
27883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * @see #setRadius(float)
27983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     */
28083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    public void setRadius(float radius) {
28183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        IMPL.setRadius(this, radius);
28283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
28383b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar
28483b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    /**
28583b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * Returns the corner radius of the CardView.
28683b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     *
28783b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * @return Corner radius of the CardView
28883b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     * @see #getRadius()
28983b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar     */
29083b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    public float getRadius() {
29183b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar        return IMPL.getRadius(this);
29283b8526436ba2e564dff99ec4c6cf46fabfdf22eYigit Boyar    }
29318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
29418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    /**
295bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Internal method used by CardView implementations to update the padding.
296c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     *
297bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * @hide
298bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     */
299bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    @Override
300bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    public void setShadowPadding(int left, int top, int right, int bottom) {
301bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        mShadowBounds.set(left, top, right, bottom);
302bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar        super.setPadding(left + mContentPadding.left, top + mContentPadding.top,
303bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar                right + mContentPadding.right, bottom + mContentPadding.bottom);
304bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
305bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
306bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    /**
30718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * Updates the backward compatible elevation of the CardView.
30818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     *
30918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @param radius The backward compatible elevation in pixels.
31018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
31118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #getCardElevation()
31218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #setMaxCardElevation(float)
31318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     */
31418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    public void setCardElevation(float radius) {
31518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        IMPL.setElevation(this, radius);
31618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    }
31718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
31818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    /**
31918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * Returns the backward compatible elevation of the CardView.
32018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     *
32118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @return Elevation of the CardView
32218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #setCardElevation(float)
32318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #getMaxCardElevation()
32418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     */
32518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    public float getCardElevation() {
32618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        return IMPL.getElevation(this);
32718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    }
32818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
32918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    /**
33018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * Updates the backward compatible elevation of the CardView.
33118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * <p>
332bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * Calling this method has no effect if device OS version is L or newer and
333bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar     * {@link #getUseCompatPadding()} is <code>false</code>.
33418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     *
33518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @param radius The backward compatible elevation in pixels.
33618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardElevation
33718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #setCardElevation(float)
33818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #getMaxCardElevation()
33918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     */
34018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    public void setMaxCardElevation(float radius) {
34118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        IMPL.setMaxElevation(this, radius);
34218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    }
34318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar
34418ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    /**
34518ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * Returns the backward compatible elevation of the CardView.
34618ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     *
34718ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @return Elevation of the CardView
34818ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #setMaxCardElevation(float)
34918ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     * @see #getCardElevation()
35018ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar     */
35118ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    public float getMaxCardElevation() {
35218ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar        return IMPL.getMaxElevation(this);
35318ef68d444a1c059041bf5b683eb612ffed22ea9Yigit Boyar    }
354bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar
355c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    /**
356c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * Returns whether CardView should add extra padding to content to avoid overlaps with rounded
357c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * corners on API versions 20 and below.
358c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     *
359c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @return True if CardView prevents overlaps with rounded corners on platforms before L.
360c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     *         Default value is <code>true</code>.
361c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     */
362bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    @Override
363c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    public boolean getPreventCornerOverlap() {
364c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        return mPreventCornerOverlap;
365c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    }
366c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar
367c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    /**
368c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * On API 20 and before, CardView does not clip the bounds of the Card for the rounded corners.
369c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * Instead, it adds padding to content so that it won't overlap with the rounded corners.
370c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * You can disable this behavior by setting this field to <code>false</code>.
371c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * <p>
372c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * Setting this value on API 21 and above does not have any effect unless you have enabled
373c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * compatibility padding.
374c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     *
375c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @param preventCornerOverlap Whether CardView should add extra padding to content to avoid
376c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     *                             overlaps with the CardView corners.
377c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @attr ref android.support.v7.cardview.R.styleable#CardView_cardPreventCornerOverlap
378c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     * @see #setUseCompatPadding(boolean)
379c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar     */
380c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar    public void setPreventCornerOverlap(boolean preventCornerOverlap) {
381c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        if (preventCornerOverlap == mPreventCornerOverlap) {
382c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar            return;
383c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        }
384c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        mPreventCornerOverlap = preventCornerOverlap;
385c42ba8c000d1e6ce85e152dfc17089a0a69e739fYigit Boyar        IMPL.onPreventCornerOverlapChanged(this);
386bdb07a1802c017efa64a5cfd8ab5a7ff4c4926b0Yigit Boyar    }
387bc943f7fa746c149c5e4c3a4eed7febe494d5df5Yigit Boyar}
388