Android 視圖高度和陰影的那點事兒

CharmainGra 7年前發布 | 13K 次閱讀 安卓開發 Android開發 移動開發

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 的設計規范的話,一定了解這個概念 。

我們可以通過屬性動畫動態改變 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 陰影效果:

https://github.com/dmytrodanylyk/shadow-layout

 

來自:http://yifeng.studio/2017/02/26/android-elevation-and-shadow/

 

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