VectorDrawable:适应不同分辨率的drawable资源

这篇文章是对VectorDrawable的简单介绍,主要参考了android官方文档。更详细的讲解请参考stylingandroid网站的3篇文章 https://blog.stylingandroid.com/vectordrawables-part-1/ ,或者关注本站将发表的翻译版本。

一、VectorDrawable

在android5.0(API Level 21)中,我们可以使用矢量图:vector drawable,vector drawable的特点是它不会因为图像的缩放而失真。在安卓开发中也就意味着你不需要为不同分辨率的设备定义不同大小的图片资源,只需一个vector drawable就够了。在安卓中与vector drawable资源对应的类是VectorDrawable。要创建一个vector drawable,你需要在xml的的元素下定义好vector drawable的形状数据。

下面的例子定义了一个心形的vector drawable:

<!-- res/drawable/heart.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    <!-- intrinsic size of the drawable -->
    android:height="256dp"
    android:width="256dp"
    <!-- size of the virtual canvas -->
    android:viewportWidth="32"
    android:viewportHeight="32">
  <!-- draw a path -->
  <path android:fillColor="#8fff"
      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" />
</vector>

其中这里最让人不解的是pathData里面的那些数字,正是这些数字让这个drawable呈现出心形。pathData指的是绘制一个图形所需要的路径信息,那么问题来了,我怎么知道该如何绘制呢?

w3c的文档中详细讲解了绘制的规则:http://www.w3.org/TR/SVG11/paths.html#PathData 。其实在svg格式的图像中也是使用这种规则,而且在安卓中[android.graphics.Path](http://developer.android.com/reference/android/graphics/Path.html) api对路径的定义也差不多是这种规则。

虽然有对path 规则的绘制教程,但是要创造出现有安卓中各种图标的效果是很难的,要让VectorDrawable有实际价值,肯定不能让开发者去想办法实现这些图形的绘制,而是原本就有很多现成的图像可用,8000个已分类好的扁平化图标(PNG/SVG/WEBFONT)  从网上的搜索结果来看svg的图标是大有人在。

二、AnimatedVectorDrawable

AnimatedVectorDrawable可以让VectorDrawable动起来。

AnimatedVectorDrawable通过改变VectorDrawable的属性来让VectorDrawable呈现动画效果,其实现实际上是试用了属性动画。

通常定义一个AnimatedVectorDrawable需要以下三个xml文件:

1.vector drawable本身:res/drawable/中定义一个有元素的xml文件,参考上面对VectorDrawable的定义。

2.vector drawable的动画文件(Animated vector drawable):res/drawable/中定义一个有元素的xml文件。

3.一个或者多个属性动画文件:res/drawable/中定义一个有元素的xml文件。

Animated vector drawable可以让和元素的属性动态变化。定义一组path或者子group,而元素定义需要绘制的路径。当你想让VectorDrawable呈现动画效果,在定义VectorDrawable的时候需要为group和path的android:name属性设置一个唯一的名字,以便在Animated vector drawable中找到它们。比如

<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

其中group的android:name为rotationGroup而path的android:name为v。

在Animated vector drawable中就分别通过rotationGroup和v找到vector drawable的group和path:

<!-- res/drawable/animvectordrawable.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@anim/rotation" />
    <target
        android:name="v"
        android:animation="@anim/path_morph" />
</animated-vector>

其中animation代表一个ObjectAnimator或者AnimatorSet ,在本例中,第一个animator将目标group旋转360度:

<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

第二个animator是将vector drawable的path元素从一个形状转变到另一个形状。但是这两个形状必须满足一定的条件:必须要有一致的命令(command)个数(逗号分割开的为命令),并且每个命令的参数个数也必须一致。

<!-- res/anim/path_morph.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        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" />
</set>