新聞中心
如果我們想創(chuàng)造更好的 Android App,我相信我們需要遵循 Material Design 的設(shè)計(jì)規(guī)范。一般而言,Material Design 是一個(gè)包含光源、材質(zhì)和投影的三維環(huán)境。如果我們想要在 App 的開發(fā)過程中,跟隨 Material Design 的設(shè)計(jì)原則,那么理解 光 與 陰影 就顯得尤為重要了。

為新華等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及新華網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì)、新華網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
我將嘗試解釋本文中的以下主題。
- Android 中的 3D
- 深度(depth)
- Z 軸,Elevation 和 Translation Z。
- 光源
- 按鈕狀態(tài)(按下和靜止)
- Outline
- 自定義的 ViewOutlineProvider
在深入到陰影和光線之前,我想告訴你我們的真實(shí)環(huán)境什么?
什么是 3D?
真實(shí)的物質(zhì)環(huán)境,是一個(gè)三維空間,這意味著所有的物體對(duì)象都有 X、Y 和 Z 維度。Z軸與顯示器的平面垂直對(duì)齊,正 Z 軸朝向觀察者延伸。在 Material Design 的世界里,每個(gè)物體都有 1dp 的厚度。
Android 的 Depth
Material Design 不同于其他的設(shè)計(jì)指南,因?yàn)樗黾恿?Depth(深度)的概念。而 Depth 在真實(shí)的視覺中,有重要的意義。
我們可以認(rèn)為我們桌子上有一層紙,如果我們?cè)儋N一張紙,我們的眼睛會(huì)覺得它有一個(gè)深度。
讓我們通過 Material Design 的應(yīng)用截圖來(lái)想象它。
讓我們來(lái)看看屏幕上的各個(gè)元素。
- 屏幕(表層 - 深度為 0 )
- CardViews
- App UI 布局
- 浮動(dòng)動(dòng)作按鈕(Floating Action Button)
這里面,每個(gè)元素都在另一個(gè)元素之上。CardView 可以滾動(dòng),所以我們可以說(shuō)***層是可滾動(dòng)的內(nèi)容,第二層是 AppBar 布局,第三層(頂層)是浮動(dòng)動(dòng)作按鈕。
那么,我們?nèi)绾味x層級(jí)?我們?nèi)绾巫層脩舾惺艿缴疃??答案是?Z 軸。
Android 中的 Z 值是什么?
View 的 Z 值有兩個(gè)組成部分:
- Elevation:高度,一個(gè)靜態(tài)值。
- Translation Z:Z軸變動(dòng)值,用于動(dòng)畫的動(dòng)態(tài)值。
我總是在想 Elevation 和 Translation Z 有什么區(qū)別。
Elevation 是靜態(tài)的,所以你***不要?jiǎng)討B(tài)的去改變他。如果你想在 Z 軸上做動(dòng)畫的效果(如按下態(tài)或者靜止態(tài)),你需要使用 Translation Z 屬性。
Translation Z 是動(dòng)態(tài)的,當(dāng)你創(chuàng)建一個(gè)空白項(xiàng)目,并在其中增加一個(gè)按鈕的時(shí)候,當(dāng)你按下它你將會(huì)看到陰影變大了。實(shí)際上 Elevation 并沒有變化,而是 Translation Z 屬性在變化。這是 Android 使用默認(rèn)的狀態(tài)列表動(dòng)畫,更改 Z 屬性。
Z Vaue = Elevation + TranslationZ
如果我們改變兩個(gè)具有 Z 值的 View,讓它們相交。Android 如何處理屏幕上的層級(jí)?讓我用一個(gè)我設(shè)計(jì)的圖表向你展示。
另外一個(gè)問題,我們?nèi)绾慰吹轿矬w的影子?我們是需要一個(gè)陰影嗎?不是的,我們是需要一個(gè)光源。
Android 中的光源是什么?
其實(shí)問題不在于是什么?而是在哪里。
在現(xiàn)實(shí)中,如果我們手持一個(gè)手電筒照桌子上的物體(從它的頂部),陰影的長(zhǎng)度會(huì)縮短,當(dāng)你降低它的時(shí)候,陰影的長(zhǎng)度會(huì)增加。
那么在 Android 的 Material Design 中,光源在哪里?在頂部?還是有角度的?經(jīng)過一番研究,我發(fā)現(xiàn)這個(gè)現(xiàn)象。
Android 中存在兩個(gè)光源,頂部那個(gè)是關(guān)鍵的光源,而另一個(gè)是環(huán)境光源,我們看到的陰影實(shí)際上是這兩個(gè)光源的組合。
讓我們看看顯示的效果。
在 Android 中,我們有很多小部件。按鈕、CardView、對(duì)話框,抽屜等所有這些都是視圖。如果有一個(gè)光源,我們就有陰影。那么我們?nèi)绾卧贏ndroid中決定 Z 值呢?Material Design 是如何規(guī)定這些的?
有一個(gè)示意圖來(lái)反映這種情況。
靜止或者按下
正如我之前提到的,在 Android Framework 中,一些動(dòng)畫是為小部件而實(shí)現(xiàn)的。如果你在布局中放置浮動(dòng)操作按鈕,默認(rèn)情況下它將具有 6dp 的 Elevation。但是你會(huì)注意到當(dāng)你按下按鈕時(shí),F(xiàn)AB 的 Elevation 將會(huì)提高到 12dp。
讓我告訴你,在這個(gè)過程中發(fā)生了什么。
其實(shí) FAB 有 6dp 的 Elevation。當(dāng)您按下按鈕時(shí),translationZ 值開始增加。ViewPropertyAnimator 通過將 translationZ 值從 0dp 更改為 6dp 來(lái)讓視圖動(dòng)起來(lái)。如果你釋放按鈕,ViewPropertyAnimator 播放動(dòng)畫,將 translationZ 從 6dp 變到 0dp。你可以為你的視圖創(chuàng)建自定義狀態(tài)列表動(dòng)畫,并將其添加到你的視圖上。
我們來(lái)看一下這個(gè)過程的流程圖。
陰影的秘密:Outline
Outline 是一個(gè)屬于 android.graphic 下的類,看看它的文檔都說(shuō)了什么
定義一個(gè)簡(jiǎn)單的形狀,用于圖形的邊界區(qū)域。
可以為 View 計(jì)算,也可以由 Drawable 計(jì)算,以驅(qū)動(dòng)由視圖投射的陰影的形狀,或剪裁視圖的內(nèi)容。
每個(gè) View 都有默認(rèn)的輪廓以顯示其陰影。如果我們創(chuàng)建一個(gè)可繪制的自定義形狀,其輪廓將根據(jù)其形狀在內(nèi)部進(jìn)行計(jì)算。所以,如果我們畫圓,輪廓將會(huì)是圓的。如果我們繪制矩形,輪廓將是矩形。
總而言之,有一個(gè) Outlin 可以讓你以不可見的方式看到這個(gè)效果。但是,如果我想創(chuàng)建一個(gè)自定義的視圖,并動(dòng)態(tài)地改變它的邊界呢?Android 會(huì)為我的自定義視圖提供了 Outline 嗎?
Android 當(dāng)然為我們提供了自定義 Outline 的辦法,那就是 : ViewOutlineProvider。
什么是 ViewOutlineProvider
在我最近的開源的 ScalingLayout 庫(kù)中,我沒有對(duì)自定義視圖實(shí)現(xiàn)陰影效果。我以為這是非常漂亮,沒有影子。但要記住 Material Design 的基礎(chǔ)知識(shí),3D,Depth,Z-Value。
這個(gè)動(dòng)畫中,我們可能無(wú)法確定那些地方是可以被點(diǎn)擊的,而且縮放布局中并沒有陰影。
接下來(lái)我們?yōu)樽远x的視圖提供動(dòng)態(tài)的輪廓。
- 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 增加了高度的支持。
更多有關(guān)于 ViewOutlineProvider 的使用中,被簡(jiǎn)化的一些基礎(chǔ)知識(shí),你可以在 ScalingLayout 中找到細(xì)節(jié)。
本文名稱:徹底理解AndroidMD設(shè)計(jì)里的“陰影”
當(dāng)前鏈接:http://fisionsoft.com.cn/article/cdghdhp.html


咨詢
建站咨詢
