標籤:圖表 override 深度 情況 layout 公眾號 對象 學習 開發
如果我們想創造更好的 Android App,我相信我們需要遵循 Material Design 的設計規範。一般而言,Material Design 是一個包含光線,材質和投影的三維環境。如果我們想要在 App 的開發過程中,跟隨 Material Design 的設計原則,那麼理解 光 與 陰影 就顯得尤為重要了。
我將嘗試解釋本文中的以下主題。
- Android 中的 3D
- 深度(Depth)
- Z 軸,Elevation 和 Translation Z。
- 光源
- 按鈕狀態(按下和靜止)
- Outline
- 自訂的 ViewOutlineProvider
在深入到陰影和光線之前,我想告訴你我們的真實環境什嗎?
什麼是 3D?
真實的物質環境,是一個三維空間,這意味著所有的物體對象都有 X、Y 和 Z 維度。Z軸與顯示器的平面垂直對齊,正 Z 軸朝向觀察者延伸。在 Material Design 的世界裡,每個物體都有 1dp 的厚度。
Android 的
Depth
Material Design 不同於其他的設計指南,因為它增加了 Depth(深度)的概念。而 Depth 在真實的視覺中,有重要的意義。
我們可以認為我們桌子上有一層紙,如果我們再貼一張紙,我們的眼睛會覺得它有一個深度。
讓我們通過 Material Design 的應用來想象它。
讓我們來看看螢幕上的各個元素。
- 螢幕(表層 - 深度為 0 )
- CardViews
- App UI 布局
- 浮動動作按鈕(Floating Action Button)
這裡面,每個元素都在另一個元素之上。CardView 可以滾動,所以我們可以說第一層是可滾動的內容,第二層是 AppBar 布局,第三層(頂層)是浮動動作按鈕。
那麼,我們如何定義層級?我們如何讓使用者感受到深度?答案是: Z 軸。
Android 中的 Z 值是什嗎?
View 的 Z 值有兩個組成部分:
- Elevation:高度,一個靜態值。
- Translation Z:Z軸變動值,用於動畫的動態值。
我總是在想 Elevation 和 Translation Z 有什麼區別。
Elevation 是靜態,所以你最好不要動態去改變他。如果你想在 Z 軸上做動畫的效果(如按下態或者靜止態),你需要使用 Translation Z 屬性。
Translation Z 是動態,當你建立一個空白項目,並在其中增加一個按鈕的時候,當你按下它你將會看到陰影變大了。實際上 Elevation 並沒有變化,而是 Translation Z 屬性在變化。這是 Android 使用預設的狀態列表動畫,更改 Z 屬性。
Z Vaue = Elevation + TranslationZ
如果我們改變兩個具有 Z 值的 View,讓它們相交。Android如何處理螢幕上的層級?讓我用一個我設計的圖表向你展示。
另外一個問題,我們如何看到物體的影子?我們是需要一個陰影嗎?不是的,我們是需要一個光源。
Android 中的光源是什嗎?
其實問題不在於是什嗎?而是在哪裡。
在現實中,如果我們手持一個手電筒照桌子上的物體(從它的頂部),陰影的長度會縮短,當你降低它的時候,陰影的長度會增加。
那麼在 Android 的 Material Design 中,光源在哪裡?在頂部?還是有角度的?經過一番研究,我發現這個現象。
Android 中存在兩個光源,頂部那個是關鍵的光源,而另一個是環境光線源,我們看到的陰影實際上是這兩個光源的組合。
讓我們看看顯示的效果。
在 Android 中,我們有很多小組件。按鈕、CardView、對話方塊,抽屜等所有這些都是視圖。如果有一個光源,我們就有陰影。那麼我們如何在Android中決定 Z 值呢?Material Design 是如何規定這些的?
有一個來反映這種情況。
靜止或者按下
正如我之前提到的,在 Android Framework 中,一些動畫是為小組件而實現的。如果你在布局中放置浮動操作按鈕,預設情況下它將具有 6dp 的 Elevation。但是你會注意到當你按下按鈕時,FAB 的 Elevation 將會提高到12 dp。
讓我告訴你,在這個過程中發生了什麼。
其實FAB有 6dp 的 Elevation。當您按下按鈕時,translationZ 值開始增加。ViewPropertyAnimator 通過將 translationZ 值從 0dp 更改為 6dp 來 讓視圖動起來。如果你釋放按鈕,ViewPropertyAnimator 播放動畫,將 translationZ 從 6dp 變到 0dp。你可以為你的視圖建立自訂狀態列表動畫,並將其添加到你的視圖上。
我們來看一下這個過程的流程圖。
陰影的秘密:Outline
Outline 是一個屬於 android.graphic 下的類,看看它的文檔都說了什麼
定義一個簡單的形狀,用於圖形的邊界地區。
可以為 View 計算,也可以由 Drawable 計算,以驅動由視圖投射的陰影的形狀,或剪裁視圖的內容。
每個 View 都有預設的輪廓以顯示其陰影。如果我們建立一個可繪製的自訂形狀,其輪廓將根據其形狀在內部進行計算。所以,如果我們畫圓,輪廓將會是圓的。如果我們繪製矩形,輪廓將是矩形。
總而言之,有一個 Outlin 可以讓你以不可見的方式看到這個效果。但是,如果我想建立一個自訂的視圖,並動態地改變它的邊界呢?Android 會為我的自訂視圖提供了 Outline 嗎?
Android 當然為我們提供了自訂 Outline 的辦法,那就是 : ViewOutlineProvider
。
什麼是 ViewOutlineProvider
在我最近的開源的 ScalingLayout 庫中,我沒有對自訂視圖實現陰影製作效果。我以為這是非常漂亮,沒有影子。但要記住 Material Design 的基礎知識,3D,Depth,Z-Value。
在這個動畫中,我們可能無法確定那些地方是可以被點擊的,而且縮放布局中並沒有陰影。
接下來我們為自訂的視圖提供動態輪廓。
public class ScalingLayoutOutlineProvider extends ViewOutlineProvider { @Override public void getOutline(View view, Outline outline) { outline.setRoundRect(0, 0, width, height, radius); }}
public class ScalingLayout extends FrameLayout { //... viewOutline = new ScalingLayoutOutlineProvider(w, h, currentRadius); setOutlineProvider(viewOutline); //.. }
這樣,我們就為自訂的 View 增加了高度的支援。
更多有關於 ViewOutlineProvider 的使用中,被簡化的一些基礎知識,你可以在 ScalingLayout 中找到細節。
https://github.com/iammert/ScalingLayout
作者 | Mert ?im?ek
翻譯 | 承香墨影
授權 承香墨影 翻譯並發布
原文地址
今天在公眾號後台回複成長『成長』,將會得到我整理的一些學習資料,也能回複『加群』,一起學習進步。
推薦閱讀:
- 站在Android開發的角度,聊聊Airbnb的Lottie
- 這些工具,讓你寫部落格的時候,只需要專註寫作!
- 找了一天找不到 Bug ? 試試 Git 的二分法吧!!!
- 如何更精準的在 Github 上搜尋開源庫?你需要這些技巧!
- Android 開發,遇上 Emoji 頭疼嗎?
徹底理解 Android 中的陰影