CardView是Android5.0(API 21)加入的新控件,當(dāng)然,在API 21以下也能用,在build.gradle的依賴?yán)锛尤胂逻呉恍芯涂梢杂昧?/p>
compile 'com.android.support:cardview-v7:23.1.1'
項(xiàng)目中要做一個(gè)卡片瀏覽的程序,卡片需要有5dp的圓角,圓角效果CardView自帶屬性就可以支持,加上app:cardCornerRadius屬性就好了,如下:
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:cardCornerRadius="5dp">
...
</android.support.v7.widget.CardView>
在API 21以上(包括)的機(jī)器實(shí)現(xiàn)了很完美的圓角效果,效果如下:

但是在API 21以下的機(jī)器出現(xiàn)了問題,以下是API 19的實(shí)現(xiàn)效果:

初步一看,雖然加上了圓角屬性,但是圖片邊上是方的。將左下角和左上角放大仔細(xì)看下:


可以看到,CardView本身是圓角效果了,但是里邊的內(nèi)容卻還是方的,并且出現(xiàn)了多余的白邊。
再仔細(xì)查看CardView的文檔,發(fā)現(xiàn)其有一個(gè)屬性cardPreventCornerOverlap
<!-- Add padding to CardView on v20 and before to prevent intersections between the Card content and rounded corners. -->
<!-- 在v20和之前的版本中添加內(nèi)邊距,這個(gè)屬性是為了防止卡片內(nèi)容和邊角的重疊 -->
<attr name="cardPreventCornerOverlap" format="boolean" />
cardPreventCornerOverlap默認(rèn)為true,意思是阻止API 20或者之前的CardView的corner和內(nèi)部元素重疊。沒有重疊就產(chǎn)生了上邊的效果,多了一條白邊。于是在xml布局文件里增加CardView的屬性app:cardPreventCornerOverlap="false",左下角和左上角效果如下:


可以看到,CardView里的元素已經(jīng)和CardView重疊了,但是元素本身沒有圓角,所以頂點(diǎn)伸出去了。到這里思路就很簡單了,將里邊的元素單獨(dú)做圓角處理。
drawable下新建shape_radius.xml文件,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="5dp" />
<solid android:color="@color/f2f2f2"></solid>
</shape>
在CardView里的元素LinearLayout加上backgroud屬性
<LinearLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@drawable/shape_radius" >
<ImageView
android:id="@+id/iv_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="@drawable/ic_person_default"/>
</LinearLayout>
左下角正常,左上角依然


圖片還需要單獨(dú)做圓角處理,這里需要的效果是,圖片的上邊兩個(gè)角需要圓角,下邊兩個(gè)角需要直角。
自定義UpRoundImageView類,繼承自ImageView,專門做圓角的繪制,代碼如下:
public class UpRoundImageView extends ImageView {
private float mRadus = 5 * SystemUtils.getDensity(CampusApplication.getCampusApplicationContext());
/*圓角的半徑,依次為左上角xy半徑,右上角,右下角,左下角*/
private float[] rids = {mRadus, mRadus, mRadus, mRadus, 0.0f,0.0f,0.0f,0.0f};
public UpRoundImageView(Context context) {
super(context);
}
public UpRoundImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public UpRoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
/**
* 畫圖
* @param canvas
*/
protected void onDraw(Canvas canvas) {
Path path = new Path();
int w = this.getWidth();
int h = this.getHeight();
/*向路徑中添加圓角矩形。radii數(shù)組定義圓角矩形的四個(gè)圓角的x,y半徑。radii長度必須為8*/
path.addRoundRect(new RectF(0,0,w,h),rids,Path.Direction.CW);
canvas.clipPath(path);
super.onDraw(canvas);
}
}
將ImageView替換成UpRoundImageView, 這樣就實(shí)現(xiàn)了全部圓角效果。
另外,可以在CardView加上app:cardElevation="3dp"屬性,這個(gè)屬性加上后可以在CardView后形成一個(gè)陰影,有卡片浮上來的感覺,更符合Material Design風(fēng)格。 xml中CardView的屬性設(shè)置為
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardUseCompatPadding="true"
app:cardCornerRadius="5dp"
app:cardPreventCornerOverlap="false"
app:cardElevation="3dp">
...
</android.support.v7.widget.CardView>
最后實(shí)現(xiàn)效果在各個(gè)平臺(tái)一致:
api 19實(shí)現(xiàn)效果

api 22實(shí)現(xiàn)效果
