聊聊 MD 设计里,阴影的那些事儿(二)

正文共: 2955字 34图

预计阅读时间: 8分钟

当你的设计师要求你在某个 View 上增加阴影效果,那你只需要认真阅读本文,阴影的问题就不再是问题。

全文太长了,我拆分成三篇来发布,今天是第二篇。

一、前言

上一篇已经介绍了一些常规的方式,在拟物化的设计里,使用标准 Api ,设定 Material Design 里的阴影效果。

有兴趣可以先看看之前的文章《聊聊 MD 设计里,阴影的那些事儿(一)》。

先来看看实现的效果,虽然多,但是它们实现的方法都不相同。

聊聊 MD 设计里,阴影的那些事儿(二)

二、使用9Patch图

2.1 什么上 9Patch 图

如果你需要兼容低版本的 Android 设备,使用 android:elevation 和 android:translationZ 是无法做到的,它们会在低版本上失效,完全没有效果,当然前提是你需要做好 Warning 的处理。

而这种阴影的效果,使用 .9图,也是一个不错的选择。

.9 图 就是 9Patch, 引用官网的介绍:

Draw 9-patch 工具是 Android Studio 中包含的一种 WYSIWYG(所见即所得)编辑器,利用此工具,您可以创建能够自动调整大小以适应视图内容和屏幕尺寸的位图图像。图像的选定部分可以根据图像内绘制的指示器在水平或竖直方向上调整比例。

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

2.2 使用 9Patch 设置阴影

直接制作一个带阴影效果的 .9 图片,然后设置好内容区域和拉伸区域,就可以在其中模拟出阴影的效果。

举个例子,使用一个 .9 图,然后设置在 ImageView 上的背景。

聊聊 MD 设计里,阴影的那些事儿(二)

在 layout-xml 上,只需要给 ImageView 设置好 android:background 就可以了。

聊聊 MD 设计里,阴影的那些事儿(二)

来看看它实现的效果:

聊聊 MD 设计里,阴影的那些事儿(二)

使用 .9 图设置的阴影,效果一般都是有保障的。不过它会作为 View 的背景被设置,所以阴影上占据 View 的大小的,所以使用图片模拟出来的阴影,View 本身的视觉效果会小。

放张单图,可能看不出效果,将一个使用 ViewCompat 实现的效果,放在一起,你就可以看到对比的效果。

聊聊 MD 设计里,阴影的那些事儿(二)

这里,两个 ImageView ,实际设置的大小,都是 100dp,但是视觉上,使用 .9 实现的效果,视觉效果就会小。

2.3 快速制作 9Patch

.9 的图,一般都是设计师会提供给我们。这里也推荐一个可以制作阴影效果的在线工具。

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

通过这个工具,你可以对 .9 图做各种调整,例如:圆角、阴影的大小、阴影的颜色等等,都是非常方便的设置。前面例子中使用的 .9 文件,就是使用此工具制作的。

聊聊 MD 设计里,阴影的那些事儿(二)

还有一种方式,就是使用 <layer-list> 这个层级的 Drawable 去模拟阴影,等于一层一层的叠加。不过使用这种方式太麻烦了,而且效果也很难做到非常的好,一般也不推荐。

2.4 9Patch 模拟阴影小结

使用 .9 图,制作阴影,基本上不需要担心效果的问题,使用起来也非常的方便。唯一的问题就是它的阴影部分,会占用 View 本身的大小,导致 View 在视觉上缩小。

总结来说,它的优点:

  1. 实现方便,只需要设置背景即可。

  2. 阴影的效果可控,颜色、圆角、阴影大小都是可以调整的。

它的缺点也非常的明显:

  1. 为了让 View 在视觉上和效果图匹配,需要预留出阴影的空间。

三、使用 FAB 的原理模拟阴影

我们知道,在 Android 对 Material Design 的效果中,有一些控件,就是自带阴影效果的,并且它也是对低版本兼容的。例如:FloatingActionButton 、CardView 等。

那么,本小结就来看看 FloatingActionButton 实现阴影的原理。

3.1 FAB 的阴影原理

就 FAB 这种有 Support.design 包支持的控件,一般都有对 不同的 Api Level 做支持处理,在 FAB 之中也是一样的,它会根据不同的 Api Level 实现不同的逻辑。

聊聊 MD 设计里,阴影的那些事儿(二)

可以看到,这里会根据 21、14、<14 三个条件,分别使用不同的实现类,它们内部实际上实现的都是相同的功能。

如果仔细观察这些 FAB 不同版本的实现类的源码,你可以发现它的阴影效果,都是基于一个 ShadowDrawableWrapper 这个 Drawable 来实现的。

例如在 FloatingActionButtonGingerbread 中,就有这样一段设置背景的代码。

聊聊 MD 设计里,阴影的那些事儿(二)

这里完全上依赖 ShadowDrawableWrapper 来做的阴影效果。

不过 ShadowDrawableWrapper 被声明的可见性为包内可见,所以我们没有办法直接使用它。

聊聊 MD 设计里,阴影的那些事儿(二)

不过,鉴于 support.design 包中的类,一般都是为了兼容做处理,这里我们只需要将它和它实现的接口 DrawableWrapper 这两个类,拷贝出来,就可以直接使用了。它们的源码都在 android.support.design/widget 包下面,非常容易找到。

它的原理是在你本文需要设置的 Drawable 之外,再包装一个 Drawable ,然后在这个包装的 Drawable 上绘制阴影。

绘制的代码挺多的,这里就不贴代码了,有兴趣可以看看它的源码,主要关注 drawShadow() 方法即可。

而如果你在拷贝源码的时候,应该能发现,它实际上是可以支持改变阴影的颜色的,如果你有这种需求,只需要再扩展它的构造方法,或者直接在 colors.xml 中配置对应的颜色,它设置颜色地方如下。

聊聊 MD 设计里,阴影的那些事儿(二)

可以看到,它主要用三个颜色来做一个渐变的阴影效果。

3.2 使用 FAB 的原理模拟阴影效果

前面说的,我们只需要将 ShadowDrawableWrapper 和 DrawableWrapper 这两个文件复制到我们的工程内,稍微修改一下它们的依赖关系。

聊聊 MD 设计里,阴影的那些事儿(二)

如果直接拷贝源码,你会发现它还依赖三个颜色,分别是用于设置阴影的颜色的,这个前面也提到过。一般而言,我们不需要设置它,直接从源码中将它们拷贝出来就可以了。

聊聊 MD 设计里,阴影的那些事儿(二)

然后我们就可以在 Java 代码中,为 View 动态设置一个阴影效果。

聊聊 MD 设计里,阴影的那些事儿(二)

这些参数,你可以自行根据效果配置,它们的含义,其实看看方法的签名,你就清楚了,这里就不再赘述了。

聊聊 MD 设计里,阴影的那些事儿(二)

那么,我们来看看使用 FAB 的 ShadowDrawableWrapper 模拟出来的阴影效果如何。

聊聊 MD 设计里,阴影的那些事儿(二)

3.3 FAB 模拟阴影效果小结

前面提到,ShadowDrawableWrapper 的原理是对原本的 Drawable 做一个包装,在外围绘制阴影的效果,所以说它实际上,阴影部分也是需要占据 View 的空间的,依然会有视觉上,View 会变小。

不过它的阴影颜色上可控的,也就是说我们可以动态的为其设置阴影的颜色,这样应该会更灵活一些。

四、小结

本篇介绍了比较常规的使用 9patch 和 FloatingActionButton 设定阴影的原理。之后还有一篇,下篇开始,再介绍一下 CardView 实现的阴影的原理和一个开源库,算是收尾。

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、Java并发编程、Web项目源码。

聊聊 MD 设计里,阴影的那些事儿(二)

推荐阅读:

聊聊 MD 设计里,阴影的那些事儿(二)

目前5000+人已关注加入我们

聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)

聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)聊聊 MD 设计里,阴影的那些事儿(二)

点赞或者分享吧~

点击『阅读原文』查看更多精彩内容

相关文章: