Material Design 規範針對 UI 元素提出了“高度”這一概念,使過去流行於擬物化設計中的陰影效果,在扁平化設計中消失了很久之後,再次顯現。不過,雖然檢視高度更多的是以陰影的形式直觀地表現在介面中,但更多地是強調一個元素相對重要性的問題。在三維空間中,擁有更高高度的 UI 元素,顯然對於使用者來講,相比於其他元素,更加凸顯其重要性,更加希望被使用者注意到,甚至被頻繁操作,這也是設計人員最想表達的初衷。
Android 中的檢視高度: Z 屬性
瞭解三維空間中的 Z 屬性,引用官網的一段介紹:
由 Z 屬性所表示的檢視高度將決定其陰影的視覺外觀:擁有較高 Z 值的檢視將投射更大且更柔和的陰影。 擁有較高 Z 值的檢視將擋住擁有較低 Z 值的檢視;不過檢視的 Z 值並不影響檢視的大小。
陰影是由提升的檢視的父項所繪製,因此將受到標準檢視裁剪的影響,而在預設情況下裁剪將由父項執行。
具體體現在 API 上,請看這一表示式:
Z = elevation + translationZ
也就是說,檢視高度由 elevation 和 translationZ 屬性決定:
- elevation:高度,靜態元件,用於提升 UI 元素高度的屬性;
- translationZ:Z 值轉換,動態元件,常用於操作 UI 元素時互動動畫的屬性。
不同檢視高度呈現出的陰影效果如圖所示:
elevation 屬性
UI 控制元件的 elevation 屬性可以設定其高度,呈現在介面中的直觀效果就是陰影效果,在 xml 佈局檔案中,通過 android:elevation
屬性設定,在 java 程式碼中通過 View 類提供的 setElevation()
方法設定。但是這個屬性存在版本相容問題,是 Android 5.0 引進的 API。所以,當 minSdkVersion
值小於21時,系統會在 xml 的對應使用地方給出一個 lint 提示:
Attribute elevation is only used in API level 21 and higher
當然你也可以選擇忽略這個提示,或者使用 tools:targetApi
屬性消除這個提示,這樣做的話,在低於 5.0 版本的系統中將不會出現陰影效果。然而,有一個更好的辦法做到相容,那就是藉助 ViewCompat
這個萬能的相容類,使 View 的 elevation 屬性相容至低版本中:
ViewCompat.setElevation(View view, float elevation)
注意:尤其要注意,檢視的陰影一定是由有輪廓的檢視投射出來的。簡單來說,就是需要設定控制元件的背景,即
android:background
屬性。我們可以選擇圖片作為背景,也可以使用<shape>
標籤定義一個 drawable 形狀,事實上,後者更為常用。
translationZ 屬性
前面提到,elevation 偏向於一個高度上的靜態提升屬性,而 translationZ 偏向於一個高度上的動態轉換屬性,可用於設定動畫,比如元素觸控狀態的轉換效果,如果你瞭解 CardView 的設計規範的話,一定了解這個概念,之前我也寫過相關的文章,呈現效果不妨參考:Android 使用CardView輕鬆實現卡片式設計。
我們可以通過屬性動畫動態改變 translationZ 屬性值,為檢視新增高度動畫,也可以在 drawable 目錄下定義一個資原始檔,然後通過 android:stateListAnimator="@drawable/selector_elevation"
屬性顯式地設定給相應的 View 控制元件。其中,selector_elevation
檔案可以這樣定義(名字可以自由編寫):
<?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/dp_4"
android:valueType="floatType" />
</item>
<item>
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="translationZ"
android:valueTo="0dp"
android:valueType="floatType" />
</item>
</selector>複製程式碼
實現陰影的其他方式
可以看出,通過設定檢視高度可以實現陰影效果。這裡需要提及一點,不要與 TextView
控制元件的 shadow 相關屬性混為一談,後者實現的是內容文字的投影效果,具體由 shadowColor、shadowRadius、shadowDx、shadowDy 四個屬性控制,與本文中介紹的檢視陰影概念大相徑庭。
像 support:design 包中的 FloatingActionBar、CardView 控制元件預設都實現了高度上的陰影效果。需要注意的是,前面我們提到的陰影效果都是由於檢視 Z 屬性提升帶來的結果,形狀由檢視的輪廓所決定的,比如圓形、方形等,至於陰影顏色,所有 UI 元素都是一致的,是無法改變的。
那麼還有沒有其他方式實現呢,如果我想改變陰影顏色呢,或者只是區域性投影呢?答案是肯定的,那就是使用帶陰影的背景圖,常見如 .9
圖。比如,系統就給我們提供了一個帶陰影效果的 .9
背景圖,你可以這樣使用:
android:background="@android:drawable/dialog_holo_light_frame"複製程式碼
或者你也可以通過 <layer-list>
標籤去一層一層定義形狀和顏色,不過比較繁瑣,不如直接使用 .9
背景圖片。這裡給大家推薦一個線上工具,通過 GUI 方式製作 .9
陰影背景圖,Android 9-patch shadow generator,如圖:
再或者,你可以嘗試一下 GitHub 上的這個開源庫,借鑑一下作者的思路,更靈活地實現 Android App 中的 UI 陰影效果:
歡迎關注我
本文由 亦楓 創作並首發於 亦楓的個人部落格 ,同步授權微信公眾號:技術鳥(NiaoTech),歡迎關注。