对于图像数据来说,可以分为矢量和栅格数据,矢量数据是记录绘制图形的方式,栅格数据是以像素点为组织形式拼接成一个图形。从这也能看出矢量和栅格数据的各个优缺点:
对于Android系统,在5.0版本时Google推出了Vector来使用矢量数据。下面简单介绍一下在Android中Vector的用法和注意事项。
SVG -- 前端中使用,是一套语法规范;
SVG实例
vector -- 在Android中使用,vector只实现了SVG语法的path标签,为了提高解析效率。
M = moveto(M X,Y):将画笔移动到指定的坐标位置
L= lineto(L X, Y):画直线到指定的坐标位置
Z = closepath():关闭路径
H = horizontal lineto(H X): 画水平线到指定的X坐标位置
V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
实例——画一个矩形
SVG编辑器
SVG转换成vector
阿里巴巴矢量图标库
svg、Vector的优点:体积小,支持按比例缩放
PNG、SVG、Vector效果对比
在下面的介绍使用方法时,是基于sdk6.0的,对于兼容性问题在2.4章节由所介绍。
在AndroidStudio中,有两种方式直接添加转换成Vector
右键drawable文件夹,选择new,选择Vector assert,
其中一种是通过使用系统库的icon图标转换成Vector,一种是导入本地的SVG文件转换成Vector
除了自动转换,还可以手动编写一个Vector。在drawable文件夹中新建一个xml文件,然后使用vector和内部的path进行绘制。其中pathData的内容是一个矩形的路径。
添加完Vector文件之后,在layout布局文件添加一个ImageView来展示这个Vector,使用的是app:srcCompat来引用资源文件。
我们尝试在Button上设置上面的Vector资源,会发现无法设置。
可以看到,在Button上用Vector是不生效的,原因是Google工程师对Vector的兼容性做出的妥协,因为Button是带有状态的控件,无法直接使用Vector。解决的办法就是使用selector插值器来配合使用。
然后在Button控件中使用background属性
如果想要将图形增大,无需修改pathData属性,只修改android:viewportWidth和android:viewportHeight属性就可以了。
之前提到过Vector与其他栅格图像的区别,内存小、不失真,但这些并不是使用Vector的理由,其实使用Vector就是为了能够方便动态地添加动画效果。下面就以几个典型的例子来分析如何添加动态地Vector。
1.gif
实现如图所示的动画效果。
首先在drawable文件夹下创建图片的Vector资源文件:
此处由于是需要两个箭头的同时动画,这就需要为两个箭头添加不同的属性动画,所以,用group的方式进行组织,并且添加了name字段来标明。
添加完代码,可以看到是一个静态的双箭头图片。
arrow
接下来,创建两个属性动画文件,分别对应向左和向右的动画效果。
简单说明一下,android:propertyName="translateX"意味着在X轴方向上运动, android:interpolator被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复),bounced(弹跳)等。"@android:interpolator/overshoot"指的是向前甩一定值后再回到原来位置。android:valueFrom="0"和android:valueTo="10"表示着效果的变化范围,对应来说是x轴上的移动位置变化,这段代码展示的是左面的箭头向右移动,相对应的右面的箭头向左移动就是android:valueFrom="0"和android:valueTo="-10"。android:valueType="floatType"指明了是运行距离的floatType类型。
然后在drawable文件夹下创建Vector动画的“粘合剂”——:
此处首先指明了 android:drawable代表图片的Vector的资源,然后在target标签下对每一个动画进行绑定,其中的name是之前的Vector图片资源文件里面的group的name属性。
最后,在粘合剂绑定完成后,用ImageView来承载这个粘合剂:
在Activity中实现这个点击事件,让动画启动:
public void anim(View view) {
ImageView imageView = (ImageView) view;
Drawable drawable = imageView.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start();
}
}
这样就能显示出我们想要的动画效果了。
接下来介绍一下颜色渐变动画的实现。
与上面的流程类似,首先创建Vector图片资源文件:
是一个静态的矩形
矩形
然后在animator文件下创建对应的属性动画文件anim_square.xml:
此处android:propertyName="fillColor"指的是动画效果是填充颜色, android:valueFrom="@android:color/holo_red_dark"和android:valueTo="@android:color/darker_gray"指的是颜色的变化范围,并且值的类型是int。
然后是创建粘合剂square_anim.xml:
最后在ImageView上承载即可,就不多介绍了。
主要介绍两种实现,一种是通过android:propertyName="trimPathStart",取值从0到1,表示路径从哪里开始绘制。0~trimPathStart区间的路径不会被绘制出来。一种是通过android:propertyName="pathData"定义路径的数据,路径由多条命令组成,格式与SVG标准的path data的d属性完全相同,路径命令的参数定义在viewport视图的坐标系,也就是说需要编写SVG格式的路径语句。
首先介绍第一种,看如下动画显示:
1.gif
2.gif
(1)搜索框动画
首先同样地创建Vector资源图片searchbar.xml:
分为放大镜图标和下划线图标。
接下来就是重点的显示动画
anim_search.xml:
anim_bar.xml
根据上面的定义介绍,anim_search.xml表示的是动画效果是绘制路径从有到无的变化过程,anim_bar.xml表示的是动画效果是绘制路径从无到有的变化过程。
同样地,创建粘合剂searchbar_anim.xml:
最后在ImageView中承载就可以实现上面的动画效果。
(2)星图标动画
这个动画包含两个属性动画,一个是颜色的渐变,一个是路径的变化。
Vector资源文件:
path
重点是动画文件
anim_path.xml:
通过set标签包含两个objectAnimator,两个动画同时展示出来。
最后是粘合剂path_anim.xml
第二种,通过指定SVG路径语句
5.gif
Vector资源图片fivestar.xml:
fivestar
重点是动画文件anim_fivestar.xml:
着重解释一下,选用的是android:propertyName="pathData"属性,意味着需要添加图形的SVG格式运动轨迹,其中android:valueFrom是五角星,android:valueTo是五边形,所以运动轨迹就是从五角星到五边形的过程。
粘合剂代码fivestar_anim.xml:
最后添加ImageView来承载粘合剂即可。
Vector默认支持5.0以上版本,在AppCompat23.2以上版本支持向下兼容:
静态Vector支持Android2.1以上
动态Vector支持Android3.0以上
几乎可以兼容大部分使用场景
在上面讲到过,在Button上使用Vector必须通过Selector来完成的,在向下兼容时,需要在Activity的前面加上:
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
为了向下兼容,影响了类似DrawableContainers(DrawableContainers which reference other drawables resources which contain only a vector resource)这样的类。它的一个典型,就是Selector(StateListDrawable也是),这个属于Google工程师对于向下兼容的无奈之举吧。
(1)向下兼容
Path Morphing,即路径变换动画,(举例来说,圆形变矩形,五角星变五边形)在Android pre-L版本下是无法使用的。目前此问题是动态兼容上最大的问题。
Path Interpolation,即路径插值器,在Android pre-L版本只能使用系统的插值器,不能自定义。
Path Animation,即路径动画,这个一般使用贝塞尔曲线来代替,所以没有太大影响。
(2)向上兼容
因为考虑到兼容性的问题,会使用AppCompat库做兼容性工作。
例如,继承了AppCompatActivity,在布局文件中又指定了ImageView的srcCompat,但是AnimatedVectorDrawableCompat是不支持Path Morphing动画的。解决的方法是,判断当前设备版本号,如果是L版本以下提示不支持此动画,如果在L版本以上修改为如下代码:
ImageView imageView = (ImageView) view;
AnimatedVectorDrawable drawable= (AnimatedVectorDrawable) getDrawable(R.drawable.xxx);
imageView.setImageDrawable(drawable);
if (drawable!= null) {
drawable.start();
}
(3)String.xml问题
不支持将Vector的PathData的数据,添加到String.xml中。
属性 | 解析 |
---|---|
android:name | 定义该drawable的名字 |
android:width | 定义该 drawable 的内部(intrinsic)宽度,支持所有 Android 系统支持的尺寸,通常使用 dp |
android:height | 定义该 drawable 的内部(intrinsic)高度,支持所有 Android 系统支持的尺寸,通常使用 dp |
android:viewportWidth | 定义矢量图视图的宽度,视图就是矢量图 path 路径数据所绘制的虚拟画布 |
android:viewportHeight | 定义矢量图视图的高度,视图就是矢量图 path 路径数据所绘制的虚拟画布 |
android:tint | 定义该 drawable 的 tint 颜色。默认是没有 tint 颜色的 |
android:tintMode | 定义 tint 颜色的 Porter-Duff blending 模式,默认值为 src_in |
android:autoMirrored | 设置当系统为 RTL (right-to-left) 布局的时候,是否自动镜像该图片。比如 阿拉伯语。 |
android:alpha | 该图片的透明度属性 |
属性 | 解析 |
---|---|
android:name | 定义该 path 的名字,这样在其他地方可以通过名字来引用这个路径 |
android:pathData | 和 SVG 中 d 元素一样的路径信息。 |
android:fillColor | 定义填充路径的颜色,如果没有定义则不填充路径 |
android:strokeColor | 定义如何绘制路径边框,如果没有定义则不显示边框 |
android:strokeWidth | 定义路径边框的粗细尺寸 |
android:strokeAlpha | 定义路径边框的透明度 |
android:fillAlpha | 定义填充路径颜色的透明度 |
android:trimPathStart | 从路径起始位置截断路径的比率,取值范围从 0 到1 |
android:trimPathEnd | 从路径结束位置截断路径的比率,取值范围从 0 到1 |
android:trimPathOffset | 设置路径截取的范围 Shift trim region (allows showed region to include the start and end), in the range from 0 to 1. |
android:strokeLineCap | 设置路径线帽的形状,取值为 butt, round, square. |
android:strokeLineJoin | 设置路径交界处的连接方式,取值为 miter,round,bevel. |
android:strokeMiterLimit | 设置斜角的上限,Sets the Miter limit for a stroked path. |
总结来说,Vector更适用于小的控件,Button,ImageView等,有更加炫的动画效果。