[译] 彻底理解 Android 中的阴影 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
plokmju88
V2EX    Android

[译] 彻底理解 Android 中的阴影

  •  
  •   plokmju88 2018-02-26 13:20:11 +08:00 11793 次点击
    这是一个创建于 2872 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果我们想创造更好的 Android App,我相信我们需要遵循Material Design 的设计规范。一般而言,Material Design 是一个包含光线,材质和投影的三维环境。如果我们想要在 App 的开发过程中,跟随 Material Design 的设计原则,那么理解 光 与 阴影 就显得尤为重要了。

    我将尝试解释本文中的以下主题。

    • Android 中的 3D
    • 深度( Depth )
    • Z 轴,Elevation 和 Translation Z。
    • 光源
    • 按钮状态(按下和静止)
    • Outline
    • 自定义的 ViewOutlineProvider

    在深入到阴影和光线之前,我想告诉你我们的真实环境什么?

    什么是 3D ?

    真实的物质环境,是一个三维空间,这意味着所有的物体对象都有 X、Y 和 Z 维度。Z 轴与显示器的平面垂直对齐,正 Z 轴朝向观察者延伸。在 Material Design 的世界里,每个物体都有 1dp 的厚度。

    Android 的 Depth

    Material Design 不同于其他的设计指南,因为它增加了 Depth (深度)的概念。而 Depth 在真实的视觉中,有重要的意义。

    我们可以认为我们桌子上有一层纸,如果我们再贴一张纸,我们的眼睛会觉得它有一个深度。

    让我们通过 Material Design 的应用截图来想象它。

    让我们来看看屏幕上的各个元素。

    • 屏幕(表层 - 深度为 0 )
    • CardViews
    • App UI 布局
    • 浮动动作按钮( Floating Action Button )

    这里面,每个元素都在另一个元素之上。CardView 可以滚动,所以我们可以说第一层是可滚动的内容,第二层是 AppBar 布局,第三层(顶层)是浮动动作按钮。

    那么,我们如何定义层级?我们如何让用户感受到深度?答案是:Z 轴。

    Android 中的 Z 值是什么?

    View 的 Z 值有两个组成部分:

    • Elevation:高度,一个静态值。
    • Translation Z:Z 轴变动值,用于动画的动态值。

    我总是在想 Elevation 和 Translation Z 有什么区别。

    Elevation 是静态的,所以你最好不要动态的去改变他。如果你想在 Z 轴上做动画的效果(如按下态或者静止态),你需要使用 Translation Z 属性。

    Translation Z 是动态的,当你创建一个空白项目,并在其中增加一个按钮的时候,当你按下它你将会看到阴影变大了。实际上 Elevation 并没有变化,而是 Translation Z 属性在变化。这是 Android 使用默认的状态列表动画,更改 Z 属性。

    Z Vaue = Elevation + TranslationZ

    如果我们改变两个具有 Z 值的 View,让它们相交。Android 如何处理屏幕上的层级?让我用一个我设计的图表向你展示。

    另外一个问题,我们如何看到物体的影子?我们是需要一个阴影吗?不是的,我们是需要一个光源。

    Android 中的光源是什么?

    其实问题不在于是什么?而是在哪里。

    在现实中,如果我们手持一个手电筒照桌子上的物体(从它的顶部),阴影的长度会缩短,当你降低它的时候,阴影的长度会增加。

    那么在 Android 的 Material Design 中,光源在哪里?在顶部?还是有角度的?经过一番研究,我发现这个现象。

    Android 中存在两个光源,顶部那个是关键的光源,而另一个是环境光源,我们看到的阴影实际上是这两个光源的组合。

    让我们看看显示的效果。

    在 Android 中,我们有很多小部件。按钮、CardView、对话框,抽屉等所有这些都是视图。如果有一个光源,我们就有阴影。那么我们如何在 Android 中决定 Z 值呢? Material Design 是如何规定这些的?

    有一个示意图来反映这种情况。

    静止或者按下

    正如我之前提到的,在 Android Framework 中,一些动画是为小部件而实现的。如果你在布局中放置浮动操作按钮,默认情况下它将具有 6dp 的 Elevation。但是你会注意到当你按下按钮时,FAB 的 Elevation 将会提高到12 dp

    让我告诉你,在这个过程中发生了什么。

    其实 FAB 有 6dp 的 Elevation。当您按下按钮时,translationZ 值开始增加。ViewPropertyAnimator 通过将 translationZ 值从 0dp 更改为 6dp 来 让视图动起来。如果你释放按钮,ViewPropertyAnimator 播放动画,将 translationZ 从 6dp 变到 0dp。你可以为你的视图创建自定义状态列表动画,并将其添加到你的视图上。

    我们来看一下这个过程的流程图。

    阴影的秘密:Outline

    Outline 是一个属于 android.graphic 下的类,看看它的文档都说了什么

    定义一个简单的形状,用于图形的边界区域。

    可以为 View 计算,也可以由 Drawable 计算,以驱动由视图投射的阴影的形状,或剪裁视图的内容。

    每个 View 都有默认的轮廓以显示其阴影。如果我们创建一个可绘制的自定义形状,其轮廓将根据其形状在内部进行计算。所以,如果我们画圆,轮廓将会是圆的。如果我们绘制矩形,轮廓将是矩形。

    总而言之,有一个 Outlin 可以让你以不可见的方式看到这个效果。但是,如果我想创建一个自定义的视图,并动态地改变它的边界呢? Android 会为我的自定义视图提供了 Outline 吗?

    Android 当然为我们提供了自定义 Outline 的办法,那就是 : ViewOutlineProvider

    什么是 ViewOutlineProvider

    在我最近的开源的 ScalingLayout 库中,我没有对自定义视图实现阴影效果。我以为这是非常漂亮,没有影子。但要记住 Material Design 的基础知识,3D,Depth,Z-Value。

    在这个动画中,我们可能无法确定那些地方是可以被点击的,而且缩放布局中并没有阴影。

    接下来我们为自定义的视图提供动态的轮廓。

    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 增加了高度的支持。

    更多有关于 ViewOutlineProvider 的使用中,被简化的一些基础知识,你可以在 ScalingLayout 中找到细节。

    https://github.com/iammert/ScalingLayout

    作者 | Mert imek

    翻译 | 承香墨影

    授权 承香墨影 翻译并发布

    原文地址

    今天在公众号后台回复成长『成长』,将会得到我整理的一些学习资料,也能回复『加群』,一起学习进步。

    推荐阅读:

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4293 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 24ms UTC 05:32 PVG 13:32 LAX 21:32 JFK 00:32
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86