Android 使用CardView輕松實現(xiàn)卡片式設計

Material design中有一種很個性的設計概念:卡片式設計(Cards),這種設計與傳統(tǒng)的List Item有所區(qū)別特铝,Cards包含更多的內(nèi)容元素和擁有自己的UI特征蛮瞄,關于Cards的設計規(guī)范可以參考官網(wǎng)介紹:

https://material.google.com/components/cards.html#

為了更好地實現(xiàn)這種 Cards UI 的設計久脯,Google在v7包中引進了一種全新的控件:CardVew,本文將從開發(fā)的角度介紹CardView的一些常見使用細節(jié)霉撵。

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

CardView-samples-01.png

上圖展示的是一個list列表撕氧,列表中的item使用了卡片式設計,主要利用CardView控件實現(xiàn)喇完,為了精簡文章內(nèi)容伦泥,這里我們將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等其他內(nèi)容 -->
            ......

        </RelativeLayout>

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

</LinearLayout>

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

排版技巧


前面我們說過富腊,CardView從本質(zhì)上屬于FrameLayout,而CardView通常包含了較多的內(nèi)容元素域帐,為了方便地排版布局中的各個元素赘被,一般借助于其他基本布局容器,比如這里我們使用了一個RelativeLayout作為CardView的唯一Child肖揣。

陰影Padding


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

圓角覆蓋


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

CardView-samples-02.png

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

Ripple效果


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

CardView-samples-03.gif

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

lift-on-touch


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

CardView-samples-04.gif

在實現(xiàn)這個效果也很簡單或颊,可以在res/drawable目錄下建立一個lift_on_touch.xml文件,內(nèi)容如下:

<?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>

即通過屬性動畫動態(tài)改變translationZ值况脆,沿著Z軸饭宾,從0dp到6dp變化批糟。這里的6dp值也是有出處的格了,參考Google I/O 2014 appAssign Elevation to Your Views。然后將其賦值給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目錄下會產(chǎn)生一個“錯誤”提示:

<selector> XML file should be in either "animator" or "drawable",not "anim"

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

關于對lift-on-touch效果的理解帕涌,YouToBe網(wǎng)站有個視頻解說摄凡,感興趣的話可以參看看,地址如下:

DesignBytes: Paper and Ink: The Materials that Matter

總結(jié)說明


CardView還有一些其他屬性可供使用蚓曼,比如cardElevation設置陰影大小亲澡,contentPadding代替普通android:padding屬性等,比較基礎纫版,本文就不一一介紹了谷扣,大家可以在官網(wǎng)上參考學習。從上面的介紹可以看出捎琐,在使用CardView時基本上都會用到一些標準配置的屬性会涎,我們可以借助style屬性,將其封裝到styles.xml文件中瑞凑,統(tǒng)一管理末秃,比如:

<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>

最后,附上本文案例項目的GitHub地址:

https://github.com/Mike-bel/MDStudySamples

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末籽御,一起剝皮案震驚了整個濱河市练慕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌技掏,老刑警劉巖铃将,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異哑梳,居然都是意外死亡劲阎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門鸠真,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悯仙,“玉大人,你說我怎么就攤上這事吠卷∥ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵祭隔,是天一觀的道長货岭。 經(jīng)常有香客問我,道長疾渴,這世上最難降的妖魔是什么千贯? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮程奠,結(jié)果婚禮上丈牢,老公的妹妹穿的比我還像新娘。我一直安慰自己瞄沙,他們只是感情好己沛,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布慌核。 她就那樣靜靜地躺著,像睡著了一般申尼。 火紅的嫁衣襯著肌膚如雪垮卓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天师幕,我揣著相機與錄音粟按,去河邊找鬼。 笑死霹粥,一個胖子當著我的面吹牛灭将,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播后控,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼庙曙,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了浩淘?” 一聲冷哼從身側(cè)響起捌朴,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎张抄,沒想到半個月后砂蔽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡署惯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年左驾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泽台。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡什荣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怀酷,到底是詐尸還是另有隱情,我是刑警寧澤嗜闻,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布蜕依,位于F島的核電站,受9級特大地震影響琉雳,放射性物質(zhì)發(fā)生泄漏样眠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一翠肘、第九天 我趴在偏房一處隱蔽的房頂上張望檐束。 院中可真熱鬧,春花似錦束倍、人聲如沸被丧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甥桂。三九已至柿究,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間黄选,已是汗流浹背蝇摸。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留办陷,地道東北人貌夕。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像民镜,于是被迫代替她去往敵國和親蜂嗽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容

  • CardView 擴展 FrameLayout 類并讓您能夠顯示卡片內(nèi)的信息殃恒,這些信息在整個平臺中擁有一致的呈現(xiàn)方...
    輕云時解被占用了閱讀 6,854評論 4 22
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評論 25 707
  • Material Design中有一種很個性的設計概念:卡片式設計(Cards)植旧,Cards擁有自己獨特的UI特征...
    小莊bb閱讀 2,997評論 1 4
  • Material Design中有一種很個性的設計概念:卡片式設計(Cards),Cards擁有自己獨特的UI特征...
    滴滴滴9527閱讀 45,304評論 3 64
  • 一.使用設備自帶字體 ios 系統(tǒng) android 系統(tǒng) winphone 系統(tǒng) 總結(jié): 問題:但是,如果微信活動...
    風月燈閱讀 1,128評論 0 0