關於 Android 陰影,大家肯定不陌生的。但是Android 中到底有多少種方式可以實現陰影效果以及各種方式之間有什么區別和優缺點,這就是我想總結的。下面我們一個一個來說:
一、各種實現陰影的方式
1. Android 在 API 21(5.0)添加了 elevation,可以很方便的在 View 上實現陰影。但是這個只在 >= API21 的手機上可以看到陰影效果,低於這個版本的就沒有陰影效果。目前市場上應用還是需要適配至 API15 的,所以需要慎重使用。
2. CardView 也可以實現陰影效果,項目中一般都是使用這種方式實現卡片式的效果並帶有陰影。使用 CardView 確實很不錯,但是它在使用的時候也是需要有注意的地方:
(1) CardView 實現陰影效果的布局,在 >= API 21 的版本上和 < 21 的版本上,如果不在代碼上做好控制,他們的顯示差異還是很大的。至於如何進行適配,可以自行查找。有圖有真相:大小呈現差異,陰影有差異:測試機型都一致,只有Android 版本差異,對於左下角的 cardBackgroundcolor 透明也是有差異的。左側為 API 15 、 右側為 API 22
(2) CardView 在 >= API21 的版本上實現陰影效果也是通過 elevation 來實現的,最終的渲染是調用 native 方法進行的。在使用過程中發現這樣一個問題,在不同位置的 View 陰影的方向是不一樣的。不知道你們發現沒,它模擬的場景就是 光源的位置在屏幕中心的正上方,然后 View 的位置由光源的位置決定。陰影方向不一致,這一點造成了我在開發中的一個 BUG,很頭痛啊,這也是一個 BUG,后面會有解決這個 。有圖有真相:
(3)如果有對陰影顏色有要求的需求, CardView 不好意思,臣妾做不到啊。哈哈,CardView 黑的差不多了。
3. Shape 來實現陰影。通過這種方式來實現陰影,由於shape是作為背景來使用的,陰影的存在有可能使內容顯示在陰影部分即陰影也占位哈。硬傷啊,當然你可以手動設置 margin 或者 padding 值控制內容的顯示位置,當然要是 dp 適配的哈。我們來看一下 shape 如何實現陰影:

<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <!--邊--> <item> <shape android:shape="rectangle"> <padding android:bottom="2px" android:left="1px" android:right="2px" android:top="1px" /> <solid android:color="#00CCCCCC" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <padding android:bottom="2px" android:left="1px" android:right="2px" android:top="1px" /> <solid android:color="#10CCCCCC" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <padding android:bottom="2px" android:left="1px" android:right="2px" android:top="1px" /> <solid android:color="#20CCCCCC" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <padding android:bottom="2px" android:left="1px" android:right="2px" android:top="1px" /> <solid android:color="#30CCCCCC" /> <corners android:radius="5dp" /> </shape> </item> <item> <shape android:shape="rectangle"> <padding android:bottom="2px" android:left="1px" android:right="2px" android:top="1px" /> <solid android:color="#50CCCCCC" /> <corners android:radius="5dp" /> </shape> </item> <!--中心背景 --> <item> <shape android:shape="rectangle" android:useLevel="false"> <!--實心 --> <solid android:color="@color/white_f2" /> <corners android:radius="5dp" /> <size android:width="32dp" android:height="32dp"/> </shape> </item> </layer-list>
效果圖:
4. 通過 .9 圖來制作陰影,這里通過一個很好的工具來制作哈:http://inloop.github.io/shadow4android/
來看下界面:這種方式制作小的背景陰影很模糊,效果上比不過 shape。如果這個沒太大關系,這種方式很方便,不用敲代碼,哈哈。
5. 用 SCardView 來實現陰影,使用方式和 CardView 一樣,但是它是使用一套代碼,顯示不會有差異,而且可以通過設置光源的位置來控制陰影的方向以及陰影的顏色。來看下效果:
SCardView 如何在代碼中使用: 添加依賴
compile 'io.github.meetsl:SCardView:1.0'
XML 代碼:
<com.meetsl.scardview.SCardView android:layout_width="@dimen/card_size" android:layout_height="@dimen/card_size" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_margin="20dp" app:cardBackgroundColor="#80B3FF" app:cardCornerRadius="5dp" app:cardElevation="@dimen/cardview_elevation" app:cardLightDirection="RT"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:padding="5dp" android:text="RT" android:textColor="@android:color/white" android:textSize="16sp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@mipmap/home_back" /> </com.meetsl.scardview.SCardView>
二、總結各種方式
方式 | 是否有顯示差異 | 是否可以控制陰影方向 | 是否可以設置陰影顏色 | 陰影是否占位 | 是否模糊 | 繪制效率 | 其他 |
elevation | 無 | 不可控制 | 不可設置 | 不占位 | 不 | 高,通過 native 繪制 | 只在 API 21 生效 |
CardView | 有 | 不可控制 | 不可設置 | 不占位 | 不 | Api 21 上效率高,通過native 繪制 | |
shape | 無 | 可控 | 可設置 | 占位 | 不 | 一般 | |
.9 圖 | 無 | 可控,生效一次,更改需重新生成 | 可設置,更改需重新生成 | 占位 | 模糊 | 慢(加載圖片顯示) | |
SCardView | 無 | 可控 | 可設置 | 不占位 | 不 | 一般 |
陰影的各種繪制比較已經奉上,按照需求和方便程度,各取所需。就到這吧,周末愉快!
SCarView 的具體說明和使用可以看這篇: