Android CardView的使用細節

beizmkej 8年前發布 | 53K 次閱讀 安卓開發 Android開發 移動開發

Material design中有一種很個性的設計概念:卡片式設計(Cards),這種設計與傳統的List Item有所區別,Cards包含更多的內容元素和擁有自己的UI特征。

為了更好地實現這種 Cards UI 的設計,Google在v7包中引進了一種全新的控件: CardVew ,本文將從開發的角度介紹CardView的一些常見使用細節。

Google用一句話介紹了CardView:一個帶圓角和陰影背景的FrameLayout。CardView在Android Lollipop(API 21)及以上版本的系統中適配較好,本文我們以一個具體的例子來學習CardView的基本使用和注意事項,效果圖如下:

上圖展示的是一個list列表,列表中的item使用了卡片式設計,主要利用CardView控件實現,為了精簡文章內容,這里我們將item布局中的核心代碼羅列出來,加以分析:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:tools="http://schemas.android.com/tools"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">

    <android.support.v7.widget.CardView
 tools:targetApi="lollipop"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:stateListAnimator="@drawable/lift_on_touch"
 android:layout_marginLeft="@dimen/dp_8"
 android:layout_marginRight="@dimen/dp_8"
 android:layout_marginBottom="@dimen/dp_8"
 android:clickable="true"
 android:foreground="?android:attr/selectableItemBackground"
 app:cardCornerRadius="@dimen/dp_4"
 app:cardUseCompatPadding="true"
 app:cardPreventCornerOverlap="false">

        <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

            <!-- image、text等其他內容 -->
            ......

        </RelativeLayout>

    </android.support.v7.widget.CardView>

</LinearLayout>

可以看出,核心部分在于CardView的屬性使用,下面我們針對幾個特殊的屬性逐一分析,深化了解。

排版技巧

前面我們說過,CardView從本質上屬于FrameLayout,而CardView通常包含了較多的內容元素,為了方便地排版布局中的各個元素,一般借助于其他基本布局容器,比如這里我們使用了一個 RelativeLayout 作為CardView的唯一Child。

陰影Padding

在Android Lollipop之前的系統,CardView會自動添加一些額外的padding空間來繪制陰影部分,這也導致了以Lollipop為分界線的不同系統上CardView的尺寸大小不同。為了解決這個問題,有兩種方法:第一種,使用不同API版本的dimension資源適配(也就是借助values和values-21文件夾中不同的dimens.xml文件);第二種,就是使用 setUseCompatPadding 屬性,設置為true(默認值為false),讓CardView在不同系統中使用相同的padding值。

圓角覆蓋

這也是一個解決系統兼容的問題。在pre-Lollipop平臺(API 21版本之前)上,CardView不會裁剪內容元素以滿足圓角需求,而是使用添加padding的替代方案,從而使內容元素不會覆蓋CardView的圓角。而控制這個行為的屬性就是cardPreventCornerOverlap,默認值為true。在本例中我們設置了該屬性為false。這里我們看一下,在pre-Lollipop平臺中,不同cardPreventCornerOverlap值的效果對比圖(左false,右true):

顯然,默認值下自動添加padding的方式不可取,所以需要設置該屬性值為false。需要注意的一點是,該屬性的設置在Lollipop及以上版本的系統中沒有任何影響,除非cardUseCompatPadding的值為true。

Ripple效果

Cards一般都是可點擊的,為此我們使用了foreground屬性并使用系統的selectableItemBackground值,同時設置clickable為true(如果在java代碼中使用了cardView.setOnClickListener,就可以不用寫clickable屬性了),從而達到在Lollipop及以上版本系統中實現點擊時的漣漪效果(Ripple),如圖:

在pre-Lollipop版本中,則是一個普通的點擊變暗的效果,這里就不截圖展示了,如果想改變老版本的點擊效果,也可以通過版本兼容的方式另行修改。

lift-on-touch

根據官網 Material motion 部分對交互動作規范的指導,Cards、Button等視圖應該有一個觸摸抬起(lift-on-touch)的交互效果,也就是在三維立體空間上的Z軸發生位移,從而產生一個陰影加深的效果,與Ripple效果共同使用,官網給了一個很好的示例圖:

在實現這個效果也很簡單,可以在 res/drawable 目錄下建立一個 lift_on_touch.xml 文件,內容如下:

<?xml version="1.0" encoding="utf-8"?>
<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
 android:state_enabled="true"
 android:state_pressed="true">
        <set>
            <objectAnimator
 android:duration="@android:integer/config_shortAnimTime"
 android:propertyName="translationZ"
 android:valueTo="6dp"
 android:valueType="floatType"/>
        </set>
    </item>
    <item>
        <set>
            <objectAnimator
 android:duration="@android:integer/config_shortAnimTime"
 android:propertyName="translationZ"
 android:valueTo="0"
 android:valueType="floatType"/>
        </set>
    </item>
</selector>

即通過屬性動畫動態改變translationZ值,沿著Z軸,從0dp到6dp變化。然后將其賦值給 android:stateListAnimator 屬性即可。由于 stateListAnimator 屬性只適用于Lollipop及以上版本,為了隱藏xml中的版本警告,可以指定 tools:targetApi="lollipop" 。

關于這個功能,需要補充說明一點。這里的 lift_on_touch.xml ,嚴格意義上來講,屬于anim資源,同時適用于API 21及以上版本,所以按道理上來講應該將其放置在 res/anim-v21 目錄下,然后使用 @anim/lift_on_touch 賦值給 stateListAnimator 屬性,而不是例子中的 @drawable/lift_on_touch 方法。但是放置在 res/anim-v21 目錄下會產生一個“錯誤”提示:

XML file should be in either “animator” or “drawable”,not “anim”

雖然這個“錯誤”不影響編譯運行,但是對于追求完美主義的程序員們來說還是礙眼,所以本例中我選擇將其放在了 res/drawable 目錄下,大家可以自行斟酌使用。

總結說明

CardView還有一些其他屬性可供使用,比如 cardElevation 設置陰影大小, contentPadding 代替普通 android:padding 屬性等,比較基礎,本文就不一一介紹了,大家可以在官網上參考學習。從上面的介紹可以看出,在使用CardView時基本上都會用到一些標準配置的屬性,我們可以借助style屬性,將其封裝到 styles.xml 文件中,統一管理,比如:

<style name="AppCardView" parent="@style/CardView.Light">
 <item name="cardPreventCornerOverlap">false</item>
 <item name="cardUseCompatPadding">true</item>
 <item name="android:foreground">?attr/selectableItemBackground</item>
 <item name="android:stateListAnimator" tools:targetApi="lollipop">@anim/lift_up</item>
 ......
</style>

 

 

來自:http://yifeng.studio/2016/10/18/android-cardview/

 

 本文由用戶 beizmkej 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!