1. 程式人生 > >Android CardView 設定點選效果

Android CardView 設定點選效果

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

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

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:layout_margin="3dp"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
    >
注意:此佈局檔案必須在res\layout-v21下。

如果你沒使用這個支援庫或者覺得這個效果在舊版本顯得有點僵硬:
你可以嘗試自定義一個 Drawable,和上一條一樣根據不同 SDK 版本分別編寫不同的效果,在此就不多介紹自定義 Drawable 的方法。

其他注意問題:

注意不同 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/value 和 /res/value-v21 資原始檔夾於專案對應 Module 目錄下,前者放置舊版本/通用的資原始檔(瞭解的可以跳過),後者放置 21 及更高 SDK 版本的資原始檔。
  2. 在 value 內的 dimen.xml 建立一個 Dimension (<dimen> 屬性),隨便命個名(如 xxx_card_margin)並填入數值 0dp。
  3. 接著在 value-v21 資料夾內的 dimen.xml 建立名字相同的 Dimension,並填入你期望的預留邊距(一般和 CardElevation 陰影大小相同)
  4. 最後,在你佈局中的 CardView 中設定android:layout_margin="@dimen/xxx_card_margin"

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

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

除了橫向滾動列表和類似 Google Play 音樂中的帶封面圖片卡片 Item,其他地方應該儘量避免做固定高度的卡片。
舉一個錯誤例子,我之前寫的快遞查詢應用「水錶助手」,快遞卡片就是用了固定寬度(誤人子弟系列QAQ)

12202_1428217458_2213

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

components_cards9

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

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

由於缺少一些系統 API(如 RenderThread),CardView 中的 Elevation 相容實現並不完美,和真正的實現方法還是有較大的差距(不是指效果),所以呼叫 setCardElevation 也不能隨心所欲地傳入一個 Float 型,在低版本系統使用時應當處理一下傳入的數值或加上 try-catch (不推薦)。