当前位置:   article > 正文

Android 5.0 新特性

Android 5.0 新特性

Material Design

 
     
 
     

Material Design简介

Material Design是谷歌新的设计语言,谷歌希望寄由此来统一各种平台上的用户体验,Material Design的特点是干净的排版和简单的布局,以此来突出内容

Material Design对排版、材质、配色、光效、间距、文字大小、交互方式、动画轨迹都做出了建议,以帮助设计者设计出符合Material Design风格的应用。

Material Design设计语言鼓励大家使用充满活力的鲜艳色彩,并在同一界面建议使用三种色调,并保障有一个强色调,强色一般处于处于视图最底层,例如状态栏或者actionbar。通过强色调形成鲜明的对比,更容易突出内容的重要性。对于文字色彩的取值,Material Design建议在浅色背景上采用黑色,在深色背景上采用白色。重要信息和标题采用87%透明度,次要文字采用54%透明度,而更次要的说明文字可以采用26%的透明度。对于想特别突出或者可点击的文字,建议使用强色调。不同层级的视图,可以通过阴影来凸显。对于带有操作且内容突出的区域,可以使用cardview进行隔离,对于内容不太重要或者操作比较单一的区域,可以使用分割线进行隔离。

更多详情请见Material Design文档:

中文版网站 http://design.1sters.com/

英文版 http://www.google.com/design/spec/material-design/introduction.html

Material Design使用

作为我们开发者,最关心的还是如何在项目中使用Material Design风格:

  1. 设置应用的 targetSdkVersion 为21
  2. 在values目录下的style资源文件中创建一个style,让其继承自 android:Theme.Material
  3. 在AndroidManifest中指定应用的主题或者Activity的主题为我们设定的样式

谷歌官方我们提供了三种配色风格的Material Design样式:

  1. 黑色主题 Theme.Material
  2. 明亮主题 Theme.Material.Light
  3. 明亮主题黑色ActionBar Theme.Material.Light.DarkActionBar

我们也可以继承系统提供的Material Design样式,进行配色修改:

Mou icon

  1. android:colorPrimaryDark 应用的主要暗色调,statusBarColor默认使用该颜色
  2. android:statusBarColor 状态栏颜色,默认使用colorPrimaryDark
  3. android:colorPrimary 应用的主要色调,actionBar默认使用该颜色
  4. android:windowBackground 窗口背景颜色
  5. android:navigationBarColor 底部栏颜色
  6. android:colorForeground 应用的前景色,ListView的分割线,switch滑动区默认使用该颜色
  7. android:colorBackground 应用的背景色,popMenu的背景默认使用该颜色
  8. android:colorAccent 一般控件的选中效果默认采用该颜色
  9. android:colorControlNormal 控件的默认色调 
  10. android:colorControlHighlight 控件按压时的色调
  11. android:colorControlActivated 控件选中时的颜色,默认使用colorAccent
  12. android:colorButtonNormal 默认按钮的背景颜色
  13. android:textColor Button,textView的文字颜色
  14. android:textColorPrimaryDisableOnly RadioButton checkbox等控件的文字
  15. android:textColorPrimary 应用的主要文字颜色,actionBar的标题文字默认使用该颜色

主题不仅可以对ApplicationActivity使用,也可以对某一个控件单使用,或者是在xml布局中给一个根节点控件设置android:theme属性,来修改它和它所有子控件的主题。 如果我们要对特定控件实例做自定义修改,建议通过控件自身的API进行设置修改。

Material Design兼容性

Material Design主题只有在API级别为21以上才可使用,在v7支持库中提供了部分控件的Material Design主题样式,如果想使应用在android的所有版本上都能统一风格,我们可以对控件效果做自定义或者使用一些第三方的兼容包。目前最有效的做法是针对21版本创建value-21资源目录,使用Material Design风格主题,在其他版本使用v7的Theme.AppCompat.Light风格主题。


阴影和裁剪

 
     
 
     

View的z属性

Material Design建议为了凸显布局的层次,建议使用阴影效果,并且Android L为了简化大家的工作,对View进行了扩展,能使大家非常方便的创建阴影效果:

阴影

给View添加了一个新的属性:Z 属性,用于描述视图距离它父视图的高度:

在5.0之前,我们的视图都是二维的,只有x轴和y轴,现在,android新增了z轴。x轴和y轴描述了一个view的大小和位置,而z轴描述了view在父视图上抬起的视觉,体现效果就是阴影。下图的两个view的z属性分别为2dp和8dp的视觉效果:

z轴

View的Z属性可以通过elevation和translationZ进行修改。

z = elevation+translationZ

在5.0之前,我们如果想给view添加阴影效果,以体现其层次感,通常的做法是给view设置一个带阴影的背景图片,现在,我们只需要简单的修改view的Z属性,就能让其具备阴影的层次感。

Z属性会扩大view的显示区域,如果它的大小大于或等于父视图的大小,那么它的阴影效果就无法显示了,view并不会因为z属性而把自身缩小腾出空间显示阴影

Z属性不仅影响着view的阴影效果,还影响着view的绘制顺序,在同一个父view内部,Z属性越小,绘制的时机就越早。也就是优先被绘制,而z属性越大,则绘制时间越晚,后绘制的将会遮盖住先绘制的,只有Z属性相同,才按照添加的顺序绘制。

View的轮廓

在Android的世界里,所有的View都是矩形的,虽然可以给View设置背景圆形的图片,即可在界面显示出圆形的内容,但是View的大小实际上仍然是矩形,并且设置的图片也是实际上也是矩形,只是圆形意外的区域为透明色。

如果系统根据View的大小来为我们生成对应的阴影,有时候就会出现很奇怪的效果。

为了解决该类问题,View增加了一个新的描述来指明内容显示的形状,这就是轮廓。通过shape设置的背景,View会自动根据shape的形状进行轮廓判定,通过color设置的背景,View默认其轮廓和View的大小一样。但是通过图片进行背景设置,View则无法获知轮廓的形状,这个时候就需要我们程序员显示的指定。

在xml布局中,可以通过android:outlineProvider来指定轮廓的判定方式:

  1. none 即使设置了Z属性,也不会显示阴影
  2. background 会按照背景来设置阴影形状
  3. bounds 会按照View的大小来描绘阴影
  4. paddedBounds 和bounds类似,不过阴影会稍微向右偏移一点

在代码中,我们可以通过setOutlineProvider来指定一个View的轮廓:

  1. ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() {
  2. public void getOutline(View view, Outline outline) {
  3. // 可以指定圆形,矩形,圆角矩形,path
  4. outline.setOval(0, 0, view.getWidth(), view.getHeight());
  5. }
  6. };
  7. View.setOutlineProvider(viewOutlineProvider );

注意:如果采用图片作为背景,即使在xml布局中指定android:outlineProvider为background也不会显示阴影,只有通过代码中指定轮廓来显示。

View的剪裁

给View指定轮廓,可以决定阴影的显示形状,如果给View指定一个小于自身大小的轮廓,正常情况下阴影会被View遮住,这个时候View的显示内容并没有因为轮廓的缩小而缩小。

如果想根据轮廓来缩小一个View,则可以通过剪裁。如果一个View指定了轮廓,调用setClipToOutline方法,就可以根据轮廓来剪裁一个View。想要剪裁轮廓,必须要给View先指定轮廓,并且轮廓是可以被剪裁的,目前只有圆形,矩形,圆角矩形支持剪裁,可以通过outline.canClip()来判断一个轮廓是否支持剪裁。

Path剪裁不会改变View的大小,但是如果Path的范围比View要的bounds要小,则剪裁后会改变View的位置,位置偏移和Z属性有关,这可能是一个BUG,view的设计者可能在绘制阴影时根据轮廓偏移了画布,而在绘制完后忘记把画布还原了。

剪裁不会改变View的测量大小和布局大小,也不会改变View的触摸区域,剪裁只是在onDraw的时候对画布做了剪裁处理,剪裁也不同于scale,scale是调整画布matrix的缩放属性,调整后,View仍然能完整显示,而剪裁是缩小画布的剪裁区域,剪裁后我们只能看到View的一部分。

试图给View一个比较大的轮廓进行剪裁也是不成功的,实验证明剪裁后的View只能比原有体积小,扩大轮廓只会扩大轮廓的绘制区域

剪裁是一个非常消耗资源的操作,我们不应该用此来做动画效果,如果要实现这样的动画,可以使用Reveal Effect


图片和颜色

 
     
 
     

tint属性

tint属性是一个颜色值,可以对图片做颜色渲染,我们可以给view的背景设置tint色值,给ImageView的图片设置tint色值,也可以给任意Drawable或者NinePatchDrawable设置tint色值。

在应用的主题中也可以通过设置 android:tint 来给主题设置统一的颜色渲染。

tint的渲染模式有总共有16种,xml文件中可以使用6种,代码中我们可以设置16种,渲染模式决定了渲染颜色和原图颜色的取舍和合成规则:

  1. PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。
  2. PorterDuff.Mode.SRC 显示上层绘制图片
  3. PorterDuff.Mode.DST 显示下层绘制图片
  4. PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。
  5. PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。
  6. PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。
  7. PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。
  8. PorterDuff.Mode.SRC_OUT 取上层绘制非交集部分。
  9. PorterDuff.Mode.DST_OUT 取下层绘制非交集部分。
  10. PorterDuff.Mode.SRC_ATOP 取下层非交集部分与上层交集部分
  11. PorterDuff.Mode.DST_ATOP 取上层非交集部分与下层交集部分
  12. PorterDuff.Mode.XOR 取两层绘制非交集。两层绘制非交集。
  13. PorterDuff.Mode.DARKEN 上下层都显示。变暗
  14. PorterDuff.Mode.LIGHTEN 上下层都显示。变亮
  15. PorterDuff.Mode.MULTIPLY 取两层绘制交集
  16. PorterDuff.Mode.SCREEN 上下层都显示。

通过tint属性处理后的图片会和原图显示出不一样的颜色,我们可以通过这种方式利用一张图片做出图片选择器的效果,让控件在按压状态下显示另外一种颜色:

通过给图片设置tint色生成另外一种图片<bitmap xmlns:android="http://schemas.android.com/apk/res/android"        android:src="@drawable/ring"        android:tintMode="multiply"        android:tint="#5677fc" />利用新的图片生成图片选择器<selector xmlns:android="http://schemas.android.com/apk/res/android">        <item android:drawable="@drawable/tint_bitmap" android:state_pressed="true"/>        <item android:drawable="@drawable/ring" /></selector>

Palette调色版

Palette调色板,可以很方便的让我们从图片中提取颜色。并且可以指定提取某种类型的颜色。

  1. Vibrant 鲜艳的
  2. Vibrant dark鲜艳的暗色
  3. Vibrant light鲜艳的亮色
  4. Muted 柔和的
  5. Muted dark柔和的暗色
  6. Muted light柔和的亮色

对图片取色是一个比较消耗性能的操作,其内部会对图片的像素值进来遍历以分析对比,所以我们要在异步线程中去完成。

  1. 如果操作本来就属于后台线程,可以使用:
  2. Palette p = Palette.generate(Bitmap bitmap);
  3. 如果在主线程中,我们可以使用异步的方式:
  4. Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() {
  5. public void onGenerated(Palette palette) {  }
  6. });

当操作完成后或者异步回调后,我们就可以使用以下方式来获取对应的色值了,并且可以在没有获取到的情况下之指定默认值:

  1. p.getVibrantColor(int defaultColor);
  2. p.getDarkVibrantColor(int defaultColor);
  3. p.getLightVibrantColor(int defaultColor);
  4. p.getMutedColor(int defaultColor);
  5. p.getDarkMutedColor(int defaultColor);
  6. p.getLightMutedColor(int defaultColor);

在使用palette之前,bitmap提供获取指定位置的像素值:

bitmap.getPixel(x,y)

但是该方式只能获取某一点的像素值,palette是对整个bitmap的所有像素值进行分析,并选出几个像素占比比较多的像素值,这样选择出来的色值更符合图片的整体色值。

vector矢量图

矢量图也称为面向对象的图像或绘图图像,是计算机图形学中用点、直线或者多边形等基于数学方程的几何图元表示的图像。矢量图形最大的优点是无论放大、缩小或旋转等不会失真;最大的缺点是难以表现色彩层次丰富、逼真的图像效果。

Android L开始支持矢量图,我们可以用它来处理一些图形简单的icon,方便我们的适配。

Android L中对矢量图的支持是通过xml文件构建,通过矢量图的path描述来生成一个矢量图,对应的java对象为VectorDrawable。

下面是官方文档提供的一个矢量图,利用改文件,我们可以创建一个随意放大缩小都不会失真的心形。

  1. <vector xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:height="300dp"
  3. android:width="300dp"
  4. android:viewportHeight="40"
  5. android:viewportWidth="40">
  6. <path android:fillColor="#ff00ff"
  7. android:pathData="M20.5,9.5
  8. c-1.955,0,-3.83,1.268,-4.5,3
  9. c-0.67,-1.732,-2.547,-3,-4.5,-3
  10. C8.957,9.5,7,11.432,7,14
  11. c0,3.53,3.793,6.257,9,11.5
  12. c5.207,-5.242,9,-7.97,9,-11.5
  13. C25,11.432,23.043,9.5,20.5,9.5z"/>
  14. </vector>

矢量图的pathData数据就是用来描述矢量图的数学公式,其含义如下表:

命令类型使用描述代表含义举例说明
移动指令M x,yM移动绝对位置M 100,240
移动指令m x,ym移动相对于上一个点m 100,240
绘制L 或 l从当前点绘制直线到指定点L 100,100
绘制H 或 h水平直线h 100
绘制V 或 v垂直直线v 100
绘制C 或 c三次方程式贝塞尔曲线C 100,200 200,400 300,200
绘制Q 或 q二次方程式贝塞尔曲线Q 100,200 300,200
绘制S 或 s平滑三次方程式贝塞尔曲线S 100,200 200,400 300,200
绘制T 或 t平滑二次方程式贝塞尔曲线T 100,200 300,200
绘制A 或 a椭圆A 5,5 0 0 1 10,10
关闭指令Z 或 z将图形的首、尾点用直线连接Z
填充F0EvenOdd 填充规则
填充F1Nonzero 填充规则

通过path命令来进行简单的图形还是可行的,但是复杂的图形我们就需要借助工具来生成了,比如使用 Expression Design,就可以直接粘贴来自其它软件的矢量图形,然后选择导出,导出时做如后选择:文件->导出->导出属性->格式->XAML Silverlight 画布,即可得到XAML格式的矢量图形,也就是Path。

更多矢量图学习可参考:http://www.w3.org/TR/SVG11/paths.html#PathData 我们可以访问http://editor.method.ac 在线制作矢量图并导出path。


新增Widget

 
    
 
    

RecyclerView

RecyclerView是ListView的升级版,它具备了更好的性能,且更容易使用。和ListView一样,RecyclerView是用来显示大量数据的容器,并通过复用有限数量的View,来提高滚动时的性能。当你的视图上的元素经常动态的且有规律的改变时候,可以使用RecyclerView控件。

与ListView不同的是RecyclerView不再负责布局,只专注于复用机制,布局交由LayoutManager来管理。 RecyclerView仍然通过Adapter来获取需要显示的对象。

Mou icon

要使用RecyclerView组件,创建Adapter不再继承自BaseAdapter,而是应该继承自RecyclerView.Adapter类,并且最好指定一个继承自RecyclerView.ViewHolder的范型,Adapter不再要求你返回一个View,而是一个ViewHolder。

继承自Adapter后,需要实现3个抽象方法:

新的Adapter和原有的Adapter并没有太多的差别,只是不再需要我们写复用判断的逻辑,因为复用逻辑其实都是相似的,它已经有了自身的实现。和原有的Adapter一样,仍然可以通过notifyDataSetChanged来刷新UI,通过getItemViewType来获取对应位置的类型,但是它不再需要你指定有多少类型了,因为该方法已经能够判断出有多少类型。新增的onViewRecycled方法可以让使用者监听View被移除屏幕的时机,并且还提供了一个AdapterDataObserver的观察者,对外提供数据改变时的回调。

ViewHolder是对所有的单个item的封装,不仅包含了item需要显示的View,并且还包含和item相关的其它数据,例如:当前的position、之前的position、即将显示的position、被回收的次数、View的类型、是否处于显示中等信息。创建一个ViewHolder需要传递一个View对象,这个View就是该holder的显示视图,该View中通常会包含一些子视图,我们最好把这些子视图都记录在holder中,便于复用时设置不同的数据。

RecyclerView不再对布局进行管理,而是通过LayoutManager管理布局,我们可以通过继承自LayoutManager来实现特殊的布局,系统提供了三种常用的布局管理器:

  1. LinearLayoutManager 线性布局
  2. GridLayoutManager 九宫格布局
  3. StaggeredGridLayoutManager 瀑布流布局

并且每一种都可以设置横行和纵向的布局,可惜的均不能添加header,如果要添加header,我们可以在Adapter中使用不同的类型来达到该效果。

RecyclerView默认提供了item的增加和删除的动画效果,如果我们使用自定义的动画,需要继承继承RecyclerView.ItemAnimator类,通过RecyclerView.setItemAnimator()方法来设置我们自定义的动画。

CardView

在实现扁平化的UI处理上,通常离不开阴影和圆角,我们通常是让美工提供一个带有阴影和圆角效果的背景图片,现在我们有了更好的实现方式,那就是CardView。

CardView实际是一个FrameLayout类的子类,它为视图提供卡片样式,并保持在不同平台上拥有统一的风格。CardView组件可以设定阴影和圆角。

我们可以使用cardElevation属性在xml布局中设置阴影效果,在代码中可以通过setCardElevation达到同样的效果。阴影的设置和Android L中的Z属性类似。

设置圆角也相当容易,在xml中通过cardCornerRadius来设置,在代码中则使用setRadius,圆角的设置和Android L中的剪裁很相似。

如果我们想设置cardview的背景,请注意使用carBackgroundColor方法,setBackgroundColor也许会影响我们的圆角效果

ToolBar

Toolbar是android L引入的一个新控件,用于取代ActionBar,它提供了ActionBar类似的功能,但是更灵活。不像ActionBar那么固定,Toolbar更像是一般的View元素,可以被放置在view树体系的任意位置,可以应用动画,可以跟着ScrollView滚动,可以与布局中的其他View交互。当然,你还可以用Toolbar替换掉ActionBar,只需调用Activity.setActionBar()。

为了兼容更多的设备一般我们都是通过AppCompat中的android.support.v7.widget.Toolbar来使用Toolbar。

有两种使用Toolbar的方式:

  1. 将Toolbar当作actionbar来使用。这种情况一般发生在你想利用actionbar现有的一些功能(比如能够显示菜单中的操作项,响应菜单点击事件,使用ActionBarDrawerToggle等),但是又想获得比actionbar更多的控制权限。
  2. 将Toolbar当作一个独立的控件来使用,这种方式又名Standalone。

如果你要将Toolbar当作actionbar来使用,你首先要去掉actionbar,最简单的方法是使用Theme.AppCompat.NoActionBar主题。或者是设置主题的属性android:windowNoTitle为true。然后在Activity的onCreate中调用setSupportActionBar(toolbar),原本应该出现在ActionBar上的menu会自动出现在actionbar上。

Toolbar的高度、宽度、背景颜色等等一切View的属性完全取决于你,这都是因为Toolbar本质上只是个ViewGroup。将Toolbar当作一个独立的控件来使用是不需要去掉actionbar的(两者可以共存),可以使用任意主题。但是在这种情况下,menu菜单并不会自动的显示在Toolbar上,Toolbar也不会响应菜单的回调函数,如果你想让menu菜单项显示在Toolbar上,必须手动inflate menu。


兼容性

 
    
 
    

虽然Material Design新增了许多新特性,但是并不是所有新内容对对下保持了兼容。

使用v7包

v7 support libraries r21 及更高版本包含了以下Material Design特性:

  1. 使用Theme.AppCompat主题包含调色板主体属性,可以对应用的主题做统一的配色,但是不包括状态栏和底部操作栏
  2. RecyclerView和CardView被独立出来,只要引入jar包,即可适配7以上的所有版本。
  3. Palette类用于从图片提取主色调

系统组件

Theme.AppCompat主题中提供了这些组件的Material Design style:

  1. EditText
  2. Spinner
  3. CheckBox
  4. RadioButton
  5. SwitchCompat
  6. CheckedTextView
  7. Color Palette

创建多个value和layout

针对Android L我们可以创建value-v21指定Material Design主题,而在其他value中指定Theme.AppCompat。layout布局也可以采用该方式,在Android L中使用系统控件,在低版本中使用我们自定义的控件活着第三方包来达到该效果。

注意版本检查

以下特性只在Android 5.0 (API level 21) 及以上版本中可用:

  1. 转场动画
  2. 触摸反馈
  3. 圆形展示动画
  4. 路径动画
  5. 矢量图
  6. tint染色

所以在代码中遇上使用这些api的地方需要进行版本判断:

第三方支持库

RippleDrawable

提供触摸反馈特效,即5.0的button按压下的水波纹效果。

  1. https://github.com/03uk/RippleDrawable 
  2. https://github.com/siriscac/RippleView 
  3. https://github.com/balysv/material-ripple 
状态动画

https://github.com/NghiaTranUIT/Responsive-Interaction-Control 

Material Design风格的对话框

https://github.com/lewisjdeane/L-Dialogs 

Material Design风格兼容包

提供了不少控件特效 https://github.com/navasmdc/MaterialDesignLibrary

SystemBarTint

支持修改状态栏和底部操作栏 https://github.com/jgilfelt/SystemBarTint 






声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号