关于 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 如何实现阴影:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<?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 的具体说明和使用可以看这篇: