矢量图形(VectorDrawable)使用几何形状的方式来描述图像元素。矢量图形非常适合于与设备无关的简单或者合成的制图或者不需要实现真实感的场合。矢量图形的渲染是在运行时开始的,因此它可以自适应不同的屏幕,放大不会失真。
Android系统从5.0开始支持矢量图,为开发者提供了添加复杂矢量图形的强大功能,同时也提供了动画显示这些图形的方法。
VectorDrawable
在Android项目中,创建一个矢量图形,只需要在res/drawable新建xml文件,在<vector>元素下定义VectorDrawable的形状。下面的例子定义了一个心形的vector drawable:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportHeight="32"
android:viewportWidth="32">
<group
android:name="group_love"
android:pivotX="15.0"
android:pivotY="15.0">
<path
android:fillColor="@color/pink_500"
android:pathData="M20.5,9.5
c-1.955,0,-3.83,1.268,-4.5,3
c-0.67,-1.732,-2.547,-3,-4.5,-3
C8.957,9.5,7,11.432,7,14
c0,3.53,3.793,6.257,9,11.5
c5.207,-5.242,9,-7.97,9,-11.5
C25,11.432,23.043,9.5,20.5,9.5z" />
</group>
</vector>
VectorDrawable通过<path>标签来定义一条路径,<group>标签可以用来给path分组,为我们对路径的组合操作提供方便。
pathData
pathData定义了vector drawable的路径,它的值是绘制一个图形所需要的信息。
可用于定义路径(Path)的命令有:
- M = move to (移动到,从某点开始)
- L = line to (从上一点画直线到)
- H = horizontal line to (水平画直线到)
- V = vertical line to (垂直画直线到)
- C = curve to (画曲线到)
- S = smooth curve to (画平滑曲线到)
- Q = quadratic Belzier curve (二次方程曲线)
- T = smooth quadratic Belzier curve (平滑二次方程曲线)
- A = elliptical Arc (画椭圆)
- Z = close path (关闭路径,直线连接终点与起点)
注释: 以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
了解pathData有一定的必要,但让我们自己去想办法使用pathData去绘制复杂的图形有一定的困难,推荐两个有用的工具:
- 矢量图形制作工具:Adobe Illustrator; Inkscape
- 8000个已分类好的扁平化图标
VectorDrawable的pathData解析规则与svg相似,我们只需要生成或下载需要的图形的svg文件,复制里面的path即可得到想要的VectorDrawable。
AnimatedVectorDrawable
AnimatedVectorDrawable是用来实现有动画效果的VectorDrawable的,它可以让<vector>里的<group>和<path>元素的属性动态变化。基本的动画效果有平移、旋转、放大缩小、以及路径绘制、形状变换。
创建一个AnimatedVectorDrawable,需要:
存在一个要实现动画效果的VectorDrawable
存在一个或多个属性动画文件
然后在res/drawable新建xml文件,在<animated-vector>元素下定义VectorDrawable的动画。
下面的例子定义了心形vector drawable的动画:
//anim_love_bounce.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="0.6"
android:valueTo="1"
android:valueType="floatType"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:interpolator="@android:interpolator/bounce"/>
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:valueFrom="0.6"
android:valueTo="1"
android:valueType="floatType"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:interpolator="@android:interpolator/bounce" />
</set>
//avd_love.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/vd_love">
<target
android:animation="@animator/anim_love_bounce"
android:name="group_love" />
</animated-vector>
注意: <path>是没有平移(translateX,translateY)、旋转(rotation)、放大缩小(scaleX,scaleY)属性的,因此无法使用属性动画来控制<path>实现平移、旋转、放大缩小动画;当我们需要实现这些动画时,需要先将相关的<path>元素包裹在一个个的<group>元素中。
路径绘制动画
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="800"
android:interpolator="@android:interpolator/linear_out_slow_in"
android:propertyName="trimPathStart"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" />
形状变换动画
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:propertyName="pathData"
android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
android:valueType="pathType" />