Material Design
的介绍,
都是基于在 Android
环境下,其实
Material Design
是一种为了让 UI 页面更加美观的设计规范,也能够按照这种规范应用到
iOS
、
Web
上。
Material Design
是 Google 在 2014 年 I/O
大会上发布的一种新的设计规范。这种设计风格给 Android UI 设计带来了不少的变化。让页面变得美感十足。html
Material Design
是一种综合了传统优秀的设计和科技创新的设计语言。java
Material Design 的设计灵感来自现实世界中真正的物质材料。Material Design 设计语言强调根据用户行为凸显核心功能,进而为用户提供操做指引,经过鲜明、形象的颜色差。添加合适的动做来引导用户。android
Material Design
强调真实性,有立体感。Material Design 的三维体如今光、绘制面和投射阴影。 全部的材料对象都包含 x,y,z 三个维度。z 轴表明了海拔高度,而不是材料的厚度,这一点不少资料都是错误的。材料的厚度永远是 1 dp 不能改变。x ,y 就是对应了材料的长宽,能够改变。segmentfault
这里的材料在Android
世界中就是一个个的控件,咱们能够把控件想象成现实世界中的物体,规定每一个物体的厚度都是固定不变的,永远是 1dp
,x,y
就对应了控件的长和宽。api
为了体现出真实物体的感受,引入了光,阴影等一些概念,这些概念咱们下面会一一说明。bash
为了配合这种设计规范,Android 又推出了许多相关的控件。这些控件你既能够单独引用,也能够直接经过android.design
包来引入。为了配合 material desig, android 提供了新的主题、新的配合主题的组件、和自定义阴影和新动画 apimarkdown
来看看 Android 为了配合 Material Design
都增长了哪些新的控件:app
在真实的物质世界里面,是一个三维的环境。全部的物体都有 x,y,z三个维度。在 Material Design 中,每一个物体(也就是你的控件)都有 1 dp 的厚度。ide
而后这些控件还有海拔的概念,还有影子的概念,这些就体现出了 3 D的感受。oop
由于强调现实世界的真实性,引入Z
表明了控件的海拔高度。好比说:在一个桌面上,你放了一本书 A,而后在 A 上又放了一本书 B 。这个时候确定会有层次感,B 相对于桌面的海拔高度和 A 相对于桌面的海拔高度确定是不同的。在 Android 中就用 Z 来表明控件的海拔高度。
为了知足 Material Design
的层次要求,android 5.0 后增长了 Z 轴,用来表示控件的海拔,海拔的效果具体体如今阴影上。
Z = elevation + translationZ
View 中的 Z
的值有两部分组成:
注意对 translationZ 的设置,若是单纯的设置控件高度的话,应该是设置 elevation
。而不是 translationZ
elevation
:海拔高度,用来指定控件静止海拔高度 elevation
属性 也能够在代码中经过 setElevation
来设置。
在 Android 中 elevation 这个属性表明了海拔高度,这个值是永远有效的,只是若是没有阴影的话,可能体现不出来,只能经过下面的海拔演示来体现出来。
TranslationZ
: 动态海拔高度偏移高度,是一个偏移的距离,是用来做动画效果,不然不要使用。
Translation Z 是动态的,当建立一个项目,增长一个按钮,当按下按钮会阴影变大了。实际上 Elevation 并无变化,而是 Translation Z 属性在变化。这是 Android 使用默认的状态列表动画,更改 Z 属性。
按钮的动做效果,默认 FAB 有 6dp 的Elevation,当按下按钮时 translation Z 值开始增长。ViewPropertyAnimator 经过将 translation Z 的值从 0 dp改成 6 dp 来让视图动起来。若是释放按钮,ViewPropertyAnimator 播放动画,将 translationZ 从 6 dp变到 0 dp。咱们能够给咱们的视图建立自定义状态列表动画,添加到视图上。
Z 属性会扩大 View 的显示区域(主要是控件自己大小+阴影),若是它的大小大于或者等于父视图的大小,那么它的阴影效果就没法显示了,view 并不会由于 z 的属性而缩小自身去显示阴影。
Z属性不只影响着view的阴影效果,还影响着view的绘制顺序,在同一个父view内部,Z属性越小,绘制的时机就越早。也就是优先被绘制,而z属性越大,则绘制时间越晚,后绘制的将会遮盖住先绘制的,只有Z属性相同,才按照添加的顺序绘制。
其实上面介绍Z
的时候就介绍海拔了,海拔就是为了表现层次感所引入的,现实世界中都有海拔的概念,Z 的值就是表明了海拔。
海拔高度指的是从一个表面到另外一个表面之间的距离,元素的海拔高度指明了元素表面之间的距离以及阴影的深度。
海拔高度是两个表面在 Z 轴上的距离,单位也是使用的 dp,一个子元素的海拔是相对于父元素而言的。
海拔高度分为:静止状态海拔高度和动态海拔高度偏移。
静态状态海拔高度:全部的元素都有一个静止的海拔高度(elevation)。
动态海拔高度偏移:指的是从静止状态向目标海拔移动的距离(translationZ)
组件的海拔高度:
某些类型的组件具备响应式的海拔高度,会根据用户的输入(例如 正常状态、获取焦点、按下)和系统事件来改变自身的海拔。这些海拔高度的改变一般是经过动态海拔高度偏移来实现的。
动态海拔高度偏移是组件从静止海拔高度向目标海拔高度所移动的距离。全部组件在被按下时,默认所增长的海拔高度是同样的。一旦输入事件完成或取消,组件会回到原来静止的海拔高度。
这张图中,控件的海拔高度就不一样,表现出层次感。
好比这张图,手机屏幕能够当作是水平面,海拔高度为0,上面有不少控件,它们的海拔高度是不同的,就表现出层次感了。
好比 CardView 和 TextView
<RelativeLayout android:layout_width="match_parent" android:layout_height="200dp"> <androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="match_parent"> </androidx.cardview.widget.CardView> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/app_name"/> </RelativeLayout> 这样的话 TextView 是不会显示出来的,由于 TextView 的默认海拔是0 ,就被 Cardview 给挡住了,由于 CardView 的默认海拔是 2dp,若是你将 TextView 的海拔设置为 3dp 这个时候 TextView 就能够显示了。 复制代码
全部的物体都是根据父-子关系描述的,子元素会继承父元素的变化属性,好比位置、旋转、海拔高度。同级的物体在层次结构中属于同一层。
好比说:咱们桌子上有一层纸,若是咱们再贴一张纸,咱们的眼睛就会以为有一个深度。
一样的效果,左边就有深度的感受,有层次感。
深度(depth)的意思就是材质环境中全部的元素都是沿着 Z 轴水平、垂直和以不一样的深度移动,在 Z 轴的正方向而且在但是范围内的点的高度。其实就海拔。
默认状况下,全部的view都是矩形的,虽然能够给view设置背景圆形的图片,便可以在界面显示出圆形的内容,可是view的大小实际上依然是矩形,而且设置的图片实际上也是矩形的,只是圆形之外的区域是透明色。
若是根据view大小来生成对应的阴影,就会出现很奇怪的效果,(一个看起来圆形的view展现出的确实一个矩形的阴影)为了解决这个问题,view增长了一个新的描述来指明内容显示的形状,这就是轮廓。
轮廓(Outlines) 表明图形对象的外形状,并肯定了对于触摸反馈的波纹区域。
每一个 view 都有默认的轮廓(其实有的 View 也没有默认的轮廓,好比 TextView)。若是咱们自定义一个 View,其轮廓应该由咱们本身来实现其轮廓。
①经过shape设置的背景,view会自动根据shape的形状进行轮廓断定, ②经过color设置的背景,view默认其轮廓和view的大小同样。 ③可是经过图片进行背景设置,view则没法获知轮廓的形状,这个时候就须要手动进行指定了
当默认轮廓很差使,或者是咱们本身定义的View 的话,就须要咱们本身经过代码来指定轮廓了。
在代码中,能够经过setOutlineProvider来指定一个view的轮廓。
与轮廓有关的类 Outline
Outline是在 android.graphic 下的类,文档说明:
定义一个简单的形状,用于做为图形的边界区域
能够做为一个 View 计算,能够由 Drawable 计算,用来驱动投射出的阴影形状,或者裁剪 View 的内容
总之,这个类就是用来给View指定轮廓的。View 的轮廓还能够经过 outlineProvider
属性来设置,默认是 background
还有其余值bounds none paddingBounds
none:即便你设置了 evaluation 也会显示阴影
background:按背景来显示轮廓,若是 background 是颜色值,则轮廓就是 view 的大小,若是是 shape 则按shape指定的形状来做为轮廓,显示阴影 若是 background 是图片或者透明shape的话只能用代码 `setOutlineProvider()` 来指定轮廓了
bounds:View 的矩形大小做为轮廓
paddingBounds:View 的矩形大小减去 padding 的值后的大小作轮廓 paddedBounds 和bounds相似,不过阴影会稍微向右偏移一点
复制代码
若是咱们想建立一个自定义视图,并动态地去改变它的轮廓,这个时候须要使用 ViewOutlineProvider
经过ViewOutlineProvider
这个类咱们能够本身给 View 添加轮廓
public class MyViewOutlineProvider extends ViewOutlineProvider { @Override public void getOutline(View view, Outline outline) { outline.setRoundRect(0, 0, width, height, radius); } } // 这样这个 View 就有轮廓了,而后经过 setElevation 来修改海拔就能够出现阴影了 //这个方法是提供轮廓,具体的阴影经过 Z 来设置,在轮廓大小固定的状况下,修改 Z 的大小,会占用轮廓的空间,看上去轮廓在变小。 view.setOutProvider(new MyViewOutlienProvider); // 若是不想让视图有投射阴影,能够设置轮廓提供者为 null 复制代码
View 的裁剪是指将 View 按照轮廓裁剪,能改变 View 的形状,如圆形头像:
先设置轮廓
在设置根据轮廓裁剪 View,目前只支持对矩形、圆形、圆角矩形的裁剪
tvClip.setClipToOutline(true)// 设置对 View 进行裁剪
经过 outlin.canClip() 方法来检查是否支持擦肩。
上面介绍了 3D、海拔、轮廓这些基本的概念,其实这些概念最终有体现效果就是靠阴影。
阴影是一个重要的视觉提示,表示了物体的海拔和运动方向。也是指示两个面之间距离的惟一视觉元素。物体的海拔高度决定了阴影的外观。
阴影还能够用来表示物体的运动方向、表面之间的距离是增长仍是减小。
阴影提供了关于海拔、运动方向和绘制边缘的提示。不一样的海拔高度,阴影的表现效果是不一样的。
通常来讲海拔越高,阴影越大,越低阴影越小,可是海拔太大会出现阴影消失的现象(通常是超过20dp)。当物质材料表面比例改变的时候,其阴影不该该发生改变,海拔发生了变化的时候,其阴影要发生改变。
物质材料内部能够展现任何形状和颜色,但其内容不会增长材料的厚度。
阴影的产生是不一样海拔高度的材料相互叠加产生的,在 Material Design 中,虚拟的光线照射使个人物质材料出现阴影,这里的光有两种光,一种是关键灯,一种是环境灯。关键灯会建立更加锐利的方向性阴影,称为关键阴影。环境光从各个角度出现,建立扩散的柔和阴影,称为环境阴影。
材质环境中的阴影由关键灯光和环境灯光投射共同产生。 在Android和iOS开发中,当光源在沿z轴的各个位置处被“材质”表面阻挡时,会出现阴影。 在Web上,仅经过操纵y轴便可描绘阴影。 如下示例显示了海拔为6dp的卡片。
阴影由轮廓和海拔共同决定。
海拔决定了阴影的大小,轮廓决定了阴影的形状。
阴影必定须要有轮廓而后海拔增高后才能被投射出来,二者缺一不可。阴影的底层是 native
实现的而不是普通的 2D 渐变效果模拟阴影。
在 Android L 中设置阴影只需两点
Button 单纯的施加 elevation
是没有阴影效果的,由于 Button 的阴影效果由 stateListAnimatior
来决定了,若是想要本身给 Button
添加的 elevation
有效果的话,必须将 stateListAnimator = "@null"
才能够。可是若是stateListAnimator
设置为 null 后,点击的海拔高度动画就没有了,为此你能够在 Button 外套一层 LinearLayout
给 LinearLayout 设置 elevation
,记住LinearLayout
必定要有背景 。可是设置最好不须要这样,用 Button 自身的阴影效果就能够了,它的阴影会根据 Button 在页面中的位置的不一样阴影还不一样。 详见 Button
参考Materila Design中文 Materila Design官网