若是咱们想创造更好的 Android App,我相信咱们须要遵循 Material Design 的设计规范。通常而言,Material Design 是一个包含光线,材质和投影的三维环境。若是咱们想要在 App 的开发过程当中,跟随 Material Design 的设计原则,那么理解 光 与 阴影 就显得尤其重要了。android
我将尝试解释本文中的如下主题。git
在深刻到阴影和光线以前,我想告诉你咱们的真实环境什么?github
真实的物质环境,是一个三维空间,这意味着全部的物体对象都有 X、Y 和 Z 维度。Z轴与显示器的平面垂直对齐,正 Z 轴朝向观察者延伸。在 Material Design 的世界里,每一个物体都有 1dp 的厚度。ide
image布局
Material Design 不一样于其余的设计指南,由于它增长了 Depth(深度)的概念。而 Depth 在真实的视觉中,有重要的意义。动画
咱们能够认为咱们桌子上有一层纸,若是咱们再贴一张纸,咱们的眼睛会以为它有一个深度。spa
让咱们经过 Material Design 的应用截图来想象它。设计
imagecode
让咱们来看看屏幕上的各个元素。对象
这里面,每一个元素都在另外一个元素之上。CardView 能够滚动,因此咱们能够说第一层是可滚动的内容,第二层是 AppBar 布局,第三层(顶层)是浮动动做按钮。
那么,咱们如何定义层级?咱们如何让用户感觉到深度?答案是: Z 轴。
View 的 Z 值有两个组成部分:
我老是在想 Elevation 和 Translation Z 有什么区别。
Elevation 是静态的,因此你最好不要动态的去改变他。若是你想在 Z 轴上作动画的效果(如按下态或者静止态),你须要使用 Translation Z 属性。
Translation Z 是动态的,当你建立一个空白项目,并在其中增长一个按钮的时候,当你按下它你将会看到阴影变大了。实际上 Elevation 并无变化,而是 Translation Z 属性在变化。这是 Android 使用默认的状态列表动画,更改 Z 属性。
Z Vaue = Elevation + TranslationZ
若是咱们改变两个具备 Z 值的 View,让它们相交。Android如何处理屏幕上的层级?让我用一个我设计的图表向你展现。
image
另一个问题,咱们如何看到物体的影子?咱们是须要一个阴影吗?不是的,咱们是须要一个光源。
其实问题不在因而什么?而是在哪里。
在现实中,若是咱们手持一个手电筒照桌子上的物体(从它的顶部),阴影的长度会缩短,当你下降它的时候,阴影的长度会增长。
那么在 Android 的 Material Design 中,光源在哪里?在顶部?仍是有角度的?通过一番研究,我发现这个现象。
image
Android 中存在两个光源,顶部那个是关键的光源,而另外一个是环境光源,咱们看到的阴影其实是这两个光源的组合。
让咱们看看显示的效果。
image
在 Android 中,咱们有不少小部件。按钮、CardView、对话框,抽屉等全部这些都是视图。若是有一个光源,咱们就有阴影。那么咱们如何在Android中决定 Z 值呢?Material Design 是如何规定这些的?
有一个示意图来反映这种状况。
image
正如我以前提到的,在 Android Framework 中,一些动画是为小部件而实现的。若是你在布局中放置浮动操做按钮,默认状况下它将具备 6dp的 Elevation。可是你会注意到当你按下按钮时,FAB 的 Elevation 将会提升到12 dp。
让我告诉你,在这个过程当中发生了什么。
其实FAB有 6dp 的 Elevation。当您按下按钮时,translationZ值开始增长。ViewPropertyAnimator 经过将 translationZ 值从 0dp 更改成 6dp 来 让视图动起来。若是你释放按钮,ViewPropertyAnimator 播放动画,将 translationZ 从 6dp 变到 0dp。你能够为你的视图建立自定义状态列表动画,并将其添加到你的视图上。
咱们来看一下这个过程的流程图。
image
Outline 是一个属于 android.graphic 下的类,看看它的文档都说了什么
定义一个简单的形状,用于图形的边界区域。
能够为 View 计算,也能够由 Drawable 计算,以驱动由视图投射的阴影的形状,或剪裁视图的内容。
每一个 View 都有默认的轮廓以显示其阴影。若是咱们建立一个可绘制的自定义形状,其轮廓将根据其形状在内部进行计算。因此,若是咱们画圆,轮廓将会是圆的。若是咱们绘制矩形,轮廓将是矩形。
总而言之,有一个 Outlin可让你以不可见的方式看到这个效果。可是,若是我想建立一个自定义的视图,并动态地改变它的边界呢?Android 会为个人自定义视图提供了 Outline 吗?
Android 固然为咱们提供了自定义 Outline 的办法,那就是 : ViewOutlineProvider
。
在我最近的开源的 ScalingLayout库中,我没有对自定义视图实现阴影效果。我觉得这是很是漂亮,没有影子。但要记住 Material Design 的基础知识,3D,Depth,Z-Value。
image
在这个动画中,咱们可能没法肯定那些地方是能够被点击的,并且缩放布局中并无阴影。
接下来咱们为自定义的视图提供动态的轮廓。
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 增长了高度的支持。
image
更多有关于 ViewOutlineProvider 的使用中,被简化的一些基础知识,你能够在 ScalingLayout 中找到细节。
做者:承香墨影 连接:https://www.jianshu.com/p/087d4496f72c 來源:简书 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。