天天看點

關于使用 CardView 開發過程中要注意的細節

2014 年,随着 Google 推出了全新的設計語言 Material Design,還迎來了新的 Android 支援庫 v7,其中就包含了 Material Design 設計語言中關于 Card 卡片概念的實作 —— CardView。經曆了相當長的一段時間相信許多 Android 開發者都已經應用了這個控件,現在才寫這篇文章可能有點晚,但對于剛剛開始使用的開發者以及其他已經使用了一段時間但做出來效果不好的同學應該能幫上點小忙。

關于使用 CardView 開發過程中要注意的細節

正題開始~

◆ 注意不同 SDK 版本(低于 Lollipop 21)上的邊距(Margin)效果

Google 在 Android Lollipop 中引入了 Material Design 設計中的陰影(Elevation)和 Z 軸位移,其目的就是突出界面中不同元素之間的層次關系。為了統一不同系統版本的視覺效果,Google 針對 SDK 21 以下的系統給 CardView 加入一個 Elevation 相容(即 XML 中的 app:cardElevation 和 Java 代碼中的 setCardElevation)。

然而,在低版本中設定了 CardElevation 之後 CardView 會自動留出空間供陰影顯示,而 Lollipop 之後則需要手動設定 Margin 邊距來預留白間,導緻我在設定 Margin 在 Android 5.x 機器上調試好後,在 Kitkat 機器調試時發現邊距非常大,嚴重地浪費了螢幕控件。

是以,我們需要自定義一個 dimen 作為 CardView 的 Margin 值:

  1. 建立 /res/values 和 /res/values-v21 資源檔案夾于項目對應 Module 目錄下,前者放置舊版本/通用的資源檔案(了解的可以跳過),後者放置 21 及更高 SDK 版本的資源檔案。
  2. 在 values 内的 dimen.xml 建立一個 Dimension (<dimen> 屬性),随便命個名(如 xxx_card_margin)并填入數值 0dp。
  3. 接着在 values-v21 檔案夾内的 dimen.xml 建立名字相同的 Dimension,并填入你期望的預留邊距(一般和 CardElevation 陰影大小相同)
  4. 最後,在你布局中的 CardView 中設定 

    android:layout_margin="@dimen/xxx_card_margin"

這樣依賴就解決了低版本中邊距過大或者視覺效果不統一的問題了。

◆ 為你的 Card 添加點選效果

當使用 CardView 的場合是作為清單中的一個 Item 且直接單擊 Item 有相應的操作,那麼就有必要加上視覺回報來告訴使用者這個 Card 是可點選的。

關于使用 CardView 開發過程中要注意的細節

(此處用其他例子代替 CardView 示範)

如果你是用了 AppCompat v7 支援庫:

那麼你可以直接給 CardView 加上 

android:foreground="?attr/selectableItemBackground" 這個屬性會在 Lollipop 上自動加上 Ripple 效果,在舊版本則是一個變深/變亮的效果。

如果你沒使用這個支援庫或者覺得這個效果在舊版本顯得有點僵硬:

你可以嘗試自定義一個 Drawable,和上一條一樣根據不同 SDK 版本分别編寫不同的效果,在此就不多介紹自定義 Drawable 的方法。

◆ 讓點選效果更加貼近 Material Design

上面曾提到過一個概念:Z 軸位移,即決定元素層次的深度,與 Elevation 大小相加構成實際顯示的陰影深度。

在 Material Design Guidelines 中有建議卡片、按鈕這類元素觸摸時應當有一個浮起的效果,也就是增大 Z 軸位移(設計緣由可以參照 NovaDNG 在知乎的回答:http://www.zhihu.com/question/27494839/answer/36865959)

關于使用 CardView 開發過程中要注意的細節

要實作這個效果并不難,我們隻需要借助 Lollipop 的一個新屬性 

android:stateListAnimator

 (PS:這也意味着這個方法不可以用于舊版本系統QAQ)

首先,建立一個 TranslationZ 的變換動畫放在 /res/anim,自己取一個名(如 touch_raise.xml),加入以下内容:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

<?

xml

version

=

"1.0"

encoding

=

"utf-8"

?>

<

selector

xmlns:android

=

"http://schemas.android.com/apk/res/android"

>

<

item

android:state_enabled

=

"true"

android:state_pressed

=

"true"

>

<

objectAnimator

android:duration

=

"@android:integer/config_shortAnimTime"

android:propertyName

=

"translationZ"

android:valueTo

=

"@dimen/touch_raise"

android:valueType

=

"floatType"

/>

</

item

>

<

item

>

<

objectAnimator

android:duration

=

"@android:integer/config_shortAnimTime"

android:propertyName

=

"translationZ"

android:valueTo

=

"0dp"

android:valueType

=

"floatType"

/>

</

item

>

</

selector

>

然後為你需要添加效果的 CardView(其他 View 同理)所在的 Layout XML 複制多一份到 /res/layout-v21,然後在新的那份 XML 的 CardView 中加入屬性 

android:stateListAnimator="@anim/touch_raise"。 這樣,你的卡片按住時就會有浮起(陰影加深)的效果了。

◆ 盡量不要用作固定高度的 List Item

除了橫向滾動清單和類似 Google Play 音樂中的帶封面圖檔卡片 Item,其他地方應該盡量避免做固定高度的卡片。

舉一個錯誤例子,我之前寫的快遞查詢應用「水表助手」,快遞卡片就是用了固定寬度(誤人子弟系列QAQ)

關于使用 CardView 開發過程中要注意的細節

不需要用卡片的地方也不應該使用,濫用隻會讓使用者更快地厭倦你的界面設計。

關于使用 CardView 開發過程中要注意的細節

(這個是複制自官方的錯誤範例)

◆ 低版本(低于 Lollipop)的 setElevation 不是萬能的

由于缺少一些系統 API(如 RenderThread),CardView 中的 Elevation 相容實作并不完美,和真正的實作方法還是有較大的差距(不是指效果),是以調用 setCardElevation 也不能随心所欲地傳入一個 Float 型,在低版本系統使用時應當處理一下傳入的數值(似乎隻能是整數,碰到過錯誤但是沒詳細研究……懶癌請原諒)或加上 try-catch (不推薦)。

————————我是分割線————————

除了本文提到的五個點,CardView 還有許多需要注意的地方,在這裡就不一一列舉了~

對于實作 Material Design 卡片,CardView 并不是唯一的選擇,也有人通過自己寫 Drawable、Layout 來實作出性能更好的卡片效果,但對在這方面不擅長的同學來說 CardView 算是最好的選擇,畢竟是 Google 自家的東西,在效果、相容性方面都十分到位。

原文位址 http://blog.feng.moe/2015/10/24/something-about-cardview-development/