CardView相信大家都并不陌生,但是我们开发过程中大多数只关心如何使用是远远不够的,需要我们去了解google开发人员设计这个控件的原因;
通过原码我们不难发现CardView是继承至FrameLayout,位于 android.support.v7.widget包下;
通过静态块初始化了成员变量CardViewImpl(是一个接口)
static { if (VERSION.SDK_INT >= 21) { IMPL = new CardViewApi21Impl(); } else if (VERSION.SDK_INT >= 17) { IMPL = new CardViewApi17Impl(); } else { IMPL = new CardViewBaseImpl(); } IMPL.initStatic(); }
通过CardViewImpl针对不同的api版本进行了兼容和管理
然后重写了onMeasure方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { if (!(IMPL instanceof CardViewApi21Impl)) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode; switch(widthMode) { case -2147483648: case 1073741824: heightMode = (int)Math.ceil((double)IMPL.getMinWidth(this.mCardViewDelegate)); widthMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(heightMode, MeasureSpec.getSize(widthMeasureSpec)), widthMode); case 0: default: heightMode = MeasureSpec.getMode(heightMeasureSpec); switch(heightMode) { case -2147483648: case 1073741824: int minHeight = (int)Math.ceil((double)IMPL.getMinHeight(this.mCardViewDelegate)); heightMeasureSpec = MeasureSpec.makeMeasureSpec(Math.max(minHeight, MeasureSpec.getSize(heightMeasureSpec)), heightMode); case 0: default: super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } }
在onmeasure方法中根据不同的情况对布局进行了重新测量;
我们知道因为系统自带的控件不能识别我们自定义的属性,所以CardView就采用自定义FrameLayout布局来包括系统原生控件,
通过CardViewImpl来操作整个布局的LayoutParams,从而达到满足各种效果的目的,这也是google设计这个控件的初衷;
下面就针对CardView常用的属性做个汇总:
<!--app:cardBackgroundColor="@color/colorPrimary" 设置cardView背景色 -->
<!--app:cardPreventCornerOverlap="false" 取消Lollipop以下版本的padding -->
<!--app:cardUseCompatPadding="true" 为 Lollipop 及其以上版本增加一个阴影padding内边距-->
<!--app:cardCornerRadius="8dp" 设置cardView圆角效果-->
<!--app:cardElevation="10dp" 设置cardView Z轴阴影大小-->
<!--app:cardMaxElevation="6dp" 设置cardView Z轴最大阴影-->
<!--app:contentPadding="10dp" 设置内容的内边距-->
<!--app:contentPaddingBottom="12dp" 设置内容的底部内边距-->
<!--app:contentPaddingLeft="12dp" 设置内容的左边内边距-->
<!--app:contentPaddingRight="12dp" 设置内容的右边内边距-->
<!--app:contentPaddingTop="12dp" 设置内容的顶部内边距-->
<android.support.v7.widget.CardView
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="20dp"
app:cardBackgroundColor="@color/colorPrimary"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true"
app:cardCornerRadius="8dp"
app:contentPadding="10dp"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
app:cardElevation="10dp">