聊聊 Material Design 里,陰影的那些事兒沛膳!

當(dāng)你的設(shè)計(jì)師要求你在某個(gè) View 上增加陰影效果扔枫,那你只需要認(rèn)真閱讀本文,陰影的問題就不再是問題锹安。

一短荐、前言

設(shè)計(jì)師的世界,與常人不同叹哭,有時(shí)候想要扁平化的風(fēng)格搓侄,有時(shí)候又想要擬物化的風(fēng)格。而在 Material Design 出來之后话速,為 UI 元素引入了高度的概念讶踪,它可以讓某個(gè)元素更為突出,顯示出它的重要性泊交,更讓人有點(diǎn)擊的欲望乳讥。

在擬物化的設(shè)計(jì)里,UI 元素的高度廓俭,反應(yīng)在效果上云石,就是在邊框上有陰影的效果,感覺它是距離底部有一個(gè)層次的關(guān)系研乒。在 Material Design 的設(shè)計(jì)中汹忠,也大量的使用了 陰影 的效果,例如:FloatingActionButton雹熬、CardView 這些控件宽菜,都是默認(rèn)支持陰影效果的。

如果你想了解 Material Design 中竿报,更多關(guān)于陰影的設(shè)計(jì)铅乡,可以查閱官方文檔。

https://material.io/guidelines/material-design/elevation-shadows.html?hl=zh-cn

接下來烈菌,我們就來介紹一下阵幸,在 Android 的不同版本中,使用不同的方式芽世,去實(shí)現(xiàn)陰影的效果挚赊。

先來看看實(shí)現(xiàn)的效果,雖然多济瓢,但是它們實(shí)現(xiàn)的方法都不相同荠割。

/all_5.jpeg

二、陰影的效果

在擬物化的世界里葬荷,陰影主要是對(duì)三維空間中的 Z 屬性進(jìn)行操作涨共。下面是官網(wǎng)的介紹。

由 Z 屬性所表示的視圖高度將決定其陰影的視覺外觀:擁有較高 Z 值的視圖將投射更大且更柔和的陰影宠漩。 擁有較高 Z 值的視圖將擋住擁有較低 Z 值的視圖举反;不過視圖的 Z 值并不影響視圖的大小。

陰影是由提升的視圖的父項(xiàng)所繪制扒吁,因此將受到標(biāo)準(zhǔn)視圖裁剪的影響火鼻,而在默認(rèn)情況下裁剪將由父項(xiàng)執(zhí)行。

https://developer.android.com/training/material/shadows-clipping.html?hl=zh-cn#Elevation

靜態(tài)效果如下:

/shadows-depth.png

再加上雕崩,動(dòng)態(tài)的效果應(yīng)該更能讓你對(duì)陰影有所理解魁索。

三、使用標(biāo)準(zhǔn) Api

Material Design 首次出現(xiàn)在 Android 5.0 中盼铁,之后又有一些 Support 包粗蔚,讓更低的版本,對(duì) Material Design 進(jìn)行支持饶火。

而在 Api Level 21 之中鹏控,增加了兩個(gè)屬性 :

  • elevation:高度,用于提升 UI 元素高度的屬性肤寝。
  • translationZ:Z 軸的變換效果当辐。

這兩個(gè)屬性,有對(duì)應(yīng)的 xml 屬性和 setXxx() 方法鲤看,而 Z 軸的改變缘揪,主要是由這兩個(gè)屬性決定的。

Z = elevation + translationZ

所以义桂,如果你的 App 的 minSdkVersion 就是 21 的話找筝,直接使用這兩個(gè)屬性是最優(yōu)的解決辦法。

3.1 elevation 屬性

elevation 屬性慷吊,主要用于給 View 增加一個(gè)高度呻征,可以直接被加在 View 控件上,呈現(xiàn)在界面上罢浇,就是一個(gè)帶陰影的效果陆赋。

在 layout-xml 布局中,可以通過 android:elevation 屬性來設(shè)置嚷闭,而在 Java 代碼中攒岛,通過 View.setElevation() 方法來使用它。

直接使用 elevation 屬性設(shè)置即可胞锰,它接收一個(gè)高度的參數(shù)灾锯,只需要按我們的需要配置即可。

需要注意的是嗅榕,View 的陰影一定是需要有背景的 View 在視覺上增高之后顺饮,投射出來的吵聪。也就是類似于打光的陰影效果。簡單來說兼雄,就是需要為 View 設(shè)置一個(gè) Background吟逝,可以使用 android:background 屬性或者 View.setBackground() 方法設(shè)置,否者 elevation 的屬性設(shè)置將無效赦肋。這里的 Background 只需要設(shè)置一個(gè) Drawable 即可块攒,你當(dāng)然也可以選擇一個(gè)圖片或者一個(gè)純色的 <shape/> 了。

下面來看看 elevation 屬性的效果:

/setElevation.png

往深里再看看 elevation 屬性的實(shí)現(xiàn)方式佃乘。

/setElevationMethod.png

它最終還是調(diào)用的 mRenderNode 去做的操作囱井,在追蹤下去,就會(huì)發(fā)現(xiàn)它底層是用的 native 的方法實(shí)現(xiàn)的趣避,所以應(yīng)該不是我們所理解的用 2D 的漸變模擬陰影的效果庞呕。

3.2 translationZ 屬性

translationZ 屬性,主要用于給 View 增加一個(gè)在 Z 軸上的變換效果程帕。它和 elevation 配合起來千扶,就是一個(gè)一加一等于二的效果。也可以用于設(shè)置 View 的高度骆捧。

在 layout-xml 布局中澎羞,可以通過 android:translationZ 屬性來設(shè)置它,而在 Java 代碼中敛苇,可以通過 View.setTranslationZ() 方法來使用它妆绞。

一般來說,我們可以直接使用 android:translationZ 屬性來設(shè)置 View枫攀,當(dāng)你配合 android:elevation 屬性一起使用的時(shí)候括饶,它們對(duì) View 的高度是累加的,當(dāng)然你也可以只使用其中一個(gè)屬性来涨。

而看到 translationZ 這樣的屬性图焰,很輕易就聯(lián)想到了 translationX 和 translationY 了,它們實(shí)際上就是不同維度的設(shè)置蹦掐,思路上很像技羔,但是原理不同。對(duì) X卧抗、Y 軸的操作并沒有 Api Level 的限制藤滥,這一點(diǎn)需要清楚。

和 elevation 屬性一樣社裆,translationZ 也是需要配合 Background 的設(shè)置才會(huì)生效的拙绊,這個(gè)應(yīng)該不難理解。

下面我們來看看 translationZ 屬性的設(shè)置效果:

/setTranslationZ.png

使用 translationZ 屬性實(shí)現(xiàn)的效果,看著和 elevation 的效果很像标沪,而它內(nèi)部也是依賴于 mRenderNode 去做的實(shí)現(xiàn)榄攀。

3.3 ViewCompat 來兼容 Api

前面就已經(jīng)提到,當(dāng)你的 minSdkVersion 達(dá)不到 elevation 和 translationZ 這兩個(gè) Api 的要求金句,設(shè)置為 Api Level 21(Android 5.0) 以下檩赢。你在使用這兩個(gè)屬性的時(shí)候,會(huì)給你提示 Warning趴梢,如果打包的時(shí)候有 Lint 的校驗(yàn),也是會(huì)提示并且導(dǎo)致打包失敗的币他。

不過看提示你也能發(fā)現(xiàn)到底是什么問題:

Attribute elevation is only used in API level 21 and higher

如果已經(jīng)明確在低于 Api Level 21 之下的版本坞靶,都不加陰影的效果,你可以在布局中蝴悉,使用 tools:targetApi="lollipop" 來消除這個(gè) Warning彰阴。

如果你是在 Java 代碼中,為 View 動(dòng)態(tài)設(shè)置 elevation 或者 translationZ 屬性的話拍冠,除了使用 Build.VERSION_CODES.LOLLIPOP 判斷之外尿这,還可以使用 ViewCompat 這個(gè) Android 為我們提供的標(biāo)準(zhǔn)的 View 兼容類,當(dāng)然庆杜,這里推薦使用 ViewCompat射众。

既然要用到 ViewCompat 的話,那我們來看看它的原理是什么。

/ViewCompatImpl.png

在 ViewCompat 中,會(huì)有很多個(gè)實(shí)現(xiàn)了 ViewCompatBaseImpl 的接口類裁僧,它們分別對(duì)應(yīng)了不同的 Api Level 逼泣,會(huì)在靜態(tài)代碼塊中,根據(jù)當(dāng)前運(yùn)行設(shè)備的 Api Level 碌宴,做不同的實(shí)現(xiàn)。而這些,都是高版本繼承低版本的實(shí)現(xiàn)伙菜,來達(dá)到繼承兼容的效果。

ViewCompatBaseImpl 這個(gè)接口中命迈,定義了很多關(guān)于 View 的操作 Api 贩绕,這些 Api 都是存在不同的 Api 版本限制的。

在 Api Level 21 中壶愤,本身就已經(jīng)支持了這兩個(gè)屬性丧叽,也就不存在兼容性的問題了,所以它其中會(huì)直接調(diào)用 setElevation()setTranslationZ() 方法公你。

/ViewCompatV21.png

那么踊淳,我們只需要關(guān)心 Api Level 21 以下的實(shí)現(xiàn)。通常來說,我們做兼容處理迂尝,一個(gè)方案就是在低版本上脱茉,使用一些只在低版本上存在 Api,來對(duì)高版本的效果進(jìn)行模擬垄开;另外一個(gè)方案就是放棄低版本琴许,完全對(duì)它不做任何處理。

我們來看看 ViewCompat 是對(duì) Elevation 是選用的那個(gè)方案溉躲。其實(shí) Api Level 21 之下榜田,都沒有對(duì)這兩個(gè)屬性的操作方法,做任何的處理锻梳,你一路追蹤下去可以追蹤到 ViewCompatBaseImpl 箭券。

/ViewCompatBaseImpl.png

從這里可以看出,ViewCompat 沒有對(duì)這兩個(gè)方法做任何的兼容疑枯,在低版本上辩块,沒有做任何的操作,這也導(dǎo)致了你如果使用 ViewCompat 的話荆永,在低版本上是不會(huì)有陰影的效果的废亭。沒有就是沒有,這里就不再單獨(dú)展示了具钥。

那看看使用 ViewCompat 在高版本上的效果圖豆村,其實(shí)和之前的也沒啥區(qū)別,不過擺在一起看更清晰一些骂删。

/Api-demo-pic.png

3.4 標(biāo)準(zhǔn) Api 小結(jié)

到現(xiàn)在你也能看到你画,如果不在意 Api level 的話,你完全可以使用 android:elevationandroid:translationZ 兩個(gè)屬性來做的陰影的效果桃漾,效果也是非常好的坏匪,而且它的陰影實(shí)際上是不占用 View 的布局大小的,它會(huì)在原本的布局之外撬统,向外擴(kuò)散适滓,所以也不會(huì)影響 View 本身大小的視覺效果。

不過它也有缺陷恋追,你只能通過設(shè)定這兩個(gè)屬性來調(diào)整陰影的大小凭迹,沒辦法做到精確掌控,并且無法修改陰影的顏色苦囱。

最新的 Android 版本市場占有率嗅绸,你可以在這個(gè)網(wǎng)站上查到。

https://developer.android.com/about/dashboards/index.html?hl=zh-cn

截止到本文編寫的時(shí)候撕彤,低于 5.0 的版本鱼鸠,差不多在 20% 左右猛拴,是否對(duì)這部分用戶,放棄陰影的效果蚀狰,取決于你的產(chǎn)品和設(shè)計(jì)師愉昆。

/Android-level.png

如果你需要兼容低版本的設(shè)備,后面介紹的一些方法麻蹋,都可以做到跛溉,繼續(xù)往下閱讀吧。

四扮授、使用9Patch圖

4.1 什么上 9Patch 圖

如果你需要兼容低版本的 Android 設(shè)備芳室,使用 android:elevation 和 android:translationZ 是無法做到的,它們會(huì)在低版本上失效刹勃,完全沒有效果堪侯,當(dāng)然前提是你需要做好 Warning 的處理。

而這種陰影的效果深夯,使用 .9圖抖格,也是一個(gè)不錯(cuò)的選擇诺苹。

.9 圖 就是 9Patch咕晋, 引用官網(wǎng)的介紹:

Draw 9-patch 工具是 Android Studio 中包含的一種 WYSIWYG(所見即所得)編輯器,利用此工具收奔,您可以創(chuàng)建能夠自動(dòng)調(diào)整大小以適應(yīng)視圖內(nèi)容和屏幕尺寸的位圖圖像掌呜。圖像的選定部分可以根據(jù)圖像內(nèi)繪制的指示器在水平或豎直方向上調(diào)整比例。

https://developer.android.com/studio/write/draw9patch.html?hl=zh-cn

4.2 使用 9Patch 設(shè)置陰影

直接制作一個(gè)帶陰影效果的 .9 圖片坪哄,然后設(shè)置好內(nèi)容區(qū)域和拉伸區(qū)域质蕉,就可以在其中模擬出陰影的效果。

舉個(gè)例子翩肌,使用一個(gè) .9 圖模暗,然后設(shè)置在 ImageView 上的背景。

/9patch.png

在 layout-xml 上念祭,只需要給 ImageView 設(shè)置好 android:background 就可以了兑宇。

/9patch-xml.png

來看看它實(shí)現(xiàn)的效果:

/9patch-xiaoguo.png

使用 .9 圖設(shè)置的陰影,效果一般都是有保障的粱坤。不過它會(huì)作為 View 的背景被設(shè)置隶糕,所以陰影上占據(jù) View 的大小的,所以使用圖片模擬出來的陰影站玄,View 本身的視覺效果會(huì)小枚驻。

放張單圖,可能看不出效果株旷,將一個(gè)使用 ViewCompat 實(shí)現(xiàn)的效果再登,放在一起,你就可以看到對(duì)比的效果。

/9patch-duibi.png

這里霎冯,兩個(gè) ImageView 铃拇,實(shí)際設(shè)置的大小,都是 100dp沈撞,但是視覺上慷荔,使用 .9 實(shí)現(xiàn)的效果,視覺效果就會(huì)小缠俺。

4.3 快速制作 9Patch

.9 的圖显晶,一般都是設(shè)計(jì)師會(huì)提供給我們。這里也推薦一個(gè)可以制作陰影效果的在線工具壹士。

http://inloop.github.io/shadow4android/

通過這個(gè)工具磷雇,你可以對(duì) .9 圖做各種調(diào)整,例如:圓角躏救、陰影的大小唯笙、陰影的顏色等等,都是非常方便的設(shè)置盒使。前面例子中使用的 .9 文件崩掘,就是使用此工具制作的。

/9patch-web.png

還有一種方式少办,就是使用 <layer-list> 這個(gè)層級(jí)的 Drawable 去模擬陰影苞慢,等于一層一層的疊加。不過使用這種方式太麻煩了英妓,而且效果也很難做到非常的好挽放,一般也不推薦。

4.4 9Patch 模擬陰影小結(jié)

使用 .9 圖蔓纠,制作陰影辑畦,基本上不需要擔(dān)心效果的問題,使用起來也非常的方便腿倚。唯一的問題就是它的陰影部分纯出,會(huì)占用 View 本身的大小,導(dǎo)致 View 在視覺上縮小猴誊。

總結(jié)來說潦刃,它的優(yōu)點(diǎn):

  1. 實(shí)現(xiàn)方便,只需要設(shè)置背景即可懈叹。
  2. 陰影的效果可控乖杠,顏色、圓角澄成、陰影大小都是可以調(diào)整的胧洒。

它的缺點(diǎn)也非常的明顯:

  1. 為了讓 View 在視覺上和效果圖匹配畏吓,需要預(yù)留出陰影的空間。

五卫漫、使用 FAB 的原理模擬陰影

我們知道菲饼,在 Android 對(duì) Material Design 的效果中,有一些控件列赎,就是自帶陰影效果的宏悦,并且它也是對(duì)低版本兼容的。例如:FloatingActionButton 包吝、CardView 等饼煞。

那么,本小結(jié)就來看看 FloatingActionButton 實(shí)現(xiàn)陰影的原理诗越。

5.1 FAB 的陰影原理

就 FAB 這種有 Support.design 包支持的控件砖瞧,一般都有對(duì) 不同的 Api Level 做支持處理,在 FAB 之中也是一樣的嚷狞,它會(huì)根據(jù)不同的 Api Level 實(shí)現(xiàn)不同的邏輯块促。

/fab-createImpl.png

可以看到,這里會(huì)根據(jù) 21床未、14竭翠、<14 三個(gè)條件,分別使用不同的實(shí)現(xiàn)類即硼,它們內(nèi)部實(shí)際上實(shí)現(xiàn)的都是相同的功能逃片。

如果仔細(xì)觀察這些 FAB 不同版本的實(shí)現(xiàn)類的源碼屡拨,你可以發(fā)現(xiàn)它的陰影效果只酥,都是基于一個(gè) ShadowDrawableWrapper 這個(gè) Drawable 來實(shí)現(xiàn)的。

例如在 FloatingActionButtonGingerbread 中呀狼,就有這樣一段設(shè)置背景的代碼裂允。

/fab-gingerbread-background.png

這里完全上依賴 ShadowDrawableWrapper 來做的陰影效果。

不過 ShadowDrawableWrapper 被聲明的可見性為包內(nèi)可見哥艇,所以我們沒有辦法直接使用它绝编。

/fab-shadowdrawable-class.png

不過,鑒于 support.design 包中的類貌踏,一般都是為了兼容做處理十饥,這里我們只需要將它和它實(shí)現(xiàn)的接口 DrawableWrapper 這兩個(gè)類,拷貝出來祖乳,就可以直接使用了逗堵。它們的源碼都在 android.support.design/widget 包下面,非常容易找到眷昆。

它的原理是在你本文需要設(shè)置的 Drawable 之外蜒秤,再包裝一個(gè) Drawable 汁咏,然后在這個(gè)包裝的 Drawable 上繪制陰影。

繪制的代碼挺多的作媚,這里就不貼代碼了攘滩,有興趣可以看看它的源碼,主要關(guān)注 drawShadow() 方法即可纸泡。

而如果你在拷貝源碼的時(shí)候漂问,應(yīng)該能發(fā)現(xiàn),它實(shí)際上是可以支持改變陰影的顏色的女揭,如果你有這種需求级解,只需要再擴(kuò)展它的構(gòu)造方法,或者直接在 colors.xml 中配置對(duì)應(yīng)的顏色田绑,它設(shè)置顏色地方如下勤哗。

/shadowWrapper-method2.png

可以看到,它主要用三個(gè)顏色來做一個(gè)漸變的陰影效果掩驱。

5.2 使用 FAB 的原理模擬陰影效果

前面說的芒划,我們只需要將 ShadowDrawableWrapper 和 DrawableWrapper 這兩個(gè)文件復(fù)制到我們的工程內(nèi),稍微修改一下它們的依賴關(guān)系欧穴。

/fab-project-path.png

如果直接拷貝源碼民逼,你會(huì)發(fā)現(xiàn)它還依賴三個(gè)顏色,分別是用于設(shè)置陰影的顏色的涮帘,這個(gè)前面也提到過拼苍。一般而言,我們不需要設(shè)置它调缨,直接從源碼中將它們拷貝出來就可以了疮鲫。

/fab-shadow-colors.png

然后我們就可以在 Java 代碼中,為 View 動(dòng)態(tài)設(shè)置一個(gè)陰影效果弦叶。

/fab-shadow-javacode.png

這些參數(shù)俊犯,你可以自行根據(jù)效果配置,它們的含義伤哺,其實(shí)看看方法的簽名燕侠,你就清楚了,這里就不再贅述了立莉。

/shadowWrapper-method.png

那么绢彤,我們來看看使用 FAB 的 ShadowDrawableWrapper 模擬出來的陰影效果如何。

/fab-xiaoguo.png

5.3 FAB 模擬陰影效果小結(jié)

前面提到蜓耻,ShadowDrawableWrapper 的原理是對(duì)原本的 Drawable 做一個(gè)包裝茫舶,在外圍繪制陰影的效果,所以說它實(shí)際上媒熊,陰影部分也是需要占據(jù) View 的空間的奇适,依然會(huì)有視覺上坟比,View 會(huì)變小。

不過它的陰影顏色上可控的嚷往,也就是說我們可以動(dòng)態(tài)的為其設(shè)置陰影的顏色葛账,這樣應(yīng)該會(huì)更靈活一些。

六皮仁、模擬 CardView 實(shí)現(xiàn)的陰影

我們知道籍琳,在 Android 對(duì) Material Design 的效果中,有一些控件贷祈,就是自帶陰影效果的趋急,并且它也是對(duì)低版本兼容的。例如:FloatingActionButton 势誊、CardView 等呜达。

那么,本小結(jié)就來看看 CardView 實(shí)現(xiàn)陰影的原理粟耻。

6.1 CardView 的陰影原理

CardView 在 support.design 包中查近,你是找不到的,它被放在了 cardview-v7 包中挤忙,現(xiàn)在已經(jīng)可以單獨(dú)引用了霜威。

CardView-v7 包中,代碼非常的少册烈。

/cardview-lib-path.png

一共就這么幾個(gè)戈泼,一樣就可以看到來,有一些類是做 Api 版本兼容的赏僧,并且也上如此大猛。

/cardview-impl.png

在其中,還有一個(gè) RoundRectDrawableWithShadow 類次哈,它就是我們要找到胎署,CardView 實(shí)現(xiàn)的 Drawable吆录,它只在 CardViewJellybeanMr1 和 cardViewGingerbread 這兩個(gè)類中使用窑滞,CardViewApi21 中,依然是使用的 setElevation() 方法來處理的陰影恢筝。

用之前 FAB 的經(jīng)驗(yàn)哀卫,將 RoundRectDrawableWithShadow 直接拷貝出來,然后運(yùn)行你會(huì)發(fā)現(xiàn)有報(bào)錯(cuò)撬槽。主要是因?yàn)槠渲杏袀€(gè)靜態(tài)的變量 sRoundRectHelper 為空了此改,沒有被初始化。

仔細(xì)查源碼你會(huì)發(fā)現(xiàn)侄柔,它在 CardViewJellybeanMr1 和 CardViewGingerbread 的實(shí)現(xiàn)原理并不相同共啃。它們會(huì)在 initStatic() 方法中占调,對(duì) sRoundRectHelper 變量進(jìn)行初始化。

CardViewJellybeanMr1.initStatic() 方法如下:

/cardview-jellybean-initstatic.png

CardViewGingerbread.initStatic() 方法如下:

/cardview-bread-initstatic.png

可以看到它們的實(shí)現(xiàn)方法移剪,差異還是挺大的究珊。

了解清楚這些,我們只需要 RoundRectDrawableWithShadow 的構(gòu)造方法中纵苛,根據(jù) Api Level 對(duì)他們進(jìn)行不同的初始化即可剿涮,這些代碼也上拷貝出來就可以直接用的。

繪制陰影的部分都大同小異攻人,這里就不詳細(xì)看了取试,有興趣的可以執(zhí)行查看源碼幌甘,主要關(guān)注 drawShadow() 方法即可赃磨。

6.2 舉個(gè) CardView 陰影的例子

首先,將 ShadowDrawableWrapper 完整的拷貝到我們的工程里机打,并且在構(gòu)造方法中蓬坡,根據(jù) Api Level 瑟蜈,用不同的邏輯初始化 sRoundRectHelper 。

還需要將 ShadowDrawableWrapper 使用到的幾個(gè)默認(rèn)參數(shù)值也拷貝出來渣窜,當(dāng)然我們已經(jīng)有源碼了铺根,直接寫死也可以,我這里選擇將它們?cè)瓨涌截惓鰜怼?/p>

/cardview-dims.png

然后我們就可以在代碼中乔宿,使用這個(gè) RoundRectDrawableWithShadow 了位迂。

/cardview-javacode.png

最終,看看實(shí)現(xiàn)的陰影效果:

/cardview-xiaoguo.png

6.3 CardView 模擬陰影小結(jié)

CardView 模擬的陰影效果详瑞,在低版本上掂林,也上會(huì)占用 View 的原本的大小來繪制陰影,所以視覺上也會(huì)偏小坝橡。不過在高版本上泻帮,依然上使用 elevation來實(shí)現(xiàn)的,也就會(huì)造成在不同 Api Level 下计寇,顯示的效果不一致的問題锣杂。

七、使用開源庫 ShadowLayout

最后再介紹一個(gè)開源庫番宁,用一個(gè) LayoutView 來實(shí)現(xiàn)陰影的效果元莫。

Github 地址:

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

它完整的庫也只有一個(gè)類加一些屬性,整個(gè)項(xiàng)目結(jié)構(gòu)如下蝶押。

/shadowlayout-project.png

并且提供了幾個(gè)屬性踱蠢,用于配置陰影的效果。

/shadowlayout-res.png

使用起來也非常的方便棋电,它上直接繼承自 FrameLayout 的茎截,所以需要作為一個(gè)布局來使用苇侵。

/shadowlayout-xml.png

最后看看實(shí)現(xiàn)的效果。

/shadowlayout-xiaoguo.png

它基本上可以實(shí)現(xiàn)一個(gè)類陰影的效果企锌,不過應(yīng)該是算法的問題衅檀,導(dǎo)致陰影的邊緣太齊了,看著不真實(shí)霎俩,一般不推薦使用哀军。

八、結(jié)語

介紹了這么多在 Android 下實(shí)現(xiàn)陰影的效果打却,接下來給一張完整的效果圖吧杉适,如果本文都看完了,我想你應(yīng)該知道自己應(yīng)該選擇那種方案了柳击。

/WechatIMG30.jpeg

今天在承香墨影公眾號(hào)的后臺(tái)猿推,回復(fù)『成長』。我會(huì)送你一些我整理的學(xué)習(xí)資料捌肴,包含:Android反編譯蹬叭、算法、設(shè)計(jì)模式状知、Web項(xiàng)目源碼秽五。

推薦閱讀:

點(diǎn)贊或者分享吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末藻糖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子库车,更是在濱河造成了極大的恐慌,老刑警劉巖樱拴,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柠衍,死亡現(xiàn)場離奇詭異洋满,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)珍坊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門牺勾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阵漏,“玉大人驻民,你說我怎么就攤上這事÷那樱” “怎么了回还?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叹洲。 經(jīng)常有香客問我柠硕,道長,這世上最難降的妖魔是什么运提? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任蝗柔,我火速辦了婚禮,結(jié)果婚禮上民泵,老公的妹妹穿的比我還像新娘癣丧。我一直安慰自己,他們只是感情好栈妆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布坎缭。 她就那樣靜靜地躺著,像睡著了一般签钩。 火紅的嫁衣襯著肌膚如雪掏呼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天铅檩,我揣著相機(jī)與錄音憎夷,去河邊找鬼。 笑死昧旨,一個(gè)胖子當(dāng)著我的面吹牛拾给,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播兔沃,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蒋得,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了乒疏?” 一聲冷哼從身側(cè)響起额衙,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后窍侧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县踢,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年伟件,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了硼啤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡斧账,死狀恐怖谴返,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情咧织,我是刑警寧澤嗓袱,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站拯爽,受9級(jí)特大地震影響索抓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜毯炮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一逼肯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桃煎,春花似錦篮幢、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至葫辐,卻和暖如春搜锰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耿战。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工蛋叼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人剂陡。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓狈涮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鸭栖。 傳聞我的和親對(duì)象是個(gè)殘疾皇子歌馍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,074評(píng)論 25 707
  • CardView 擴(kuò)展 FrameLayout 類并讓您能夠顯示卡片內(nèi)的信息,這些信息在整個(gè)平臺(tái)中擁有一致的呈現(xiàn)方...
    輕云時(shí)解被占用了閱讀 6,853評(píng)論 4 22
  • 記得以前看過一句話暴浦,說的是深深地?zé)o奈,道的卻是不明的情感玻褪,這情感是眷戀肉渴,懈怠公荧,還是溫柔带射?寫這句話的人去了,最終也是...
    張夢(mèng)哲閱讀 643評(píng)論 0 3
  • 一循狰、近期目標(biāo):完美的伴侶 二窟社、需要重下的種子:愛與陪伴,智慧绪钥,溫暖 三.具體的播種行為 1.坐在溫暖的爐火旁灿里,我覺...
    柔光寶寶閱讀 143評(píng)論 0 0
  • 時(shí)間:11月16日 學(xué)員:高藝軒 任教老師:小美老師 教學(xué)目的: 一 :能靈活的運(yùn)用互鎖結(jié)構(gòu)在搭建中學(xué)會(huì)描述物體的...
    Letnaturetakeit閱讀 299評(píng)論 0 0