矢量可绘制对象概览

VectorDrawable 是一种矢量图形,在 XML 文件中定义为一组点、线条和曲线及其相关颜色信息。使用矢量可绘制对象的主要优势在于图片可缩放。您可以在不降低显示质量的情况下缩放图片,也就是说,可以针对不同的屏幕密度调整同一文件的大小,而不会降低图片质量。这不仅能缩减 APK 文件大小,还能减少开发者维护工作。您还可以对动画使用矢量图片,具体方法是针对各种显示屏分辨率使用多个 XML 文件,而不是多张图片。

本页及下面的视频简要介绍了如何在 XML 中创建矢量可绘制对象。Android Studio 还可以将 SVG 文件转换为矢量可绘制对象格式,如添加多密度矢量图形中所述。

Android 5.0(API 级别 21)是第一个使用 VectorDrawableAnimatedVectorDrawable 正式支持矢量可绘制对象的版本,但您可以使用提供 VectorDrawableCompatAnimatedVectorDrawableCompat 类的 Android 支持库支持较低版本。

关于 VectorDrawable 类

VectorDrawable 定义静态可绘制对象。与 SVG 格式类似,每个矢量图形定义为树状层次结构,由 pathgroup 对象构成。每个 path 都包含对象轮廓的几何图形,而 group 包含转换的详细信息。所有路径都是按照其在 XML 文件中显示的顺序绘制的。

图 1. 矢量可绘制资源的层次结构示例

借助 Vector Asset Studio 工具,可轻松地将矢量图形作为 XML 文件添加到项目中。

示例 XML

以下示例 VectorDrawable XML 文件会渲染一张充电模式下电池的图片。

    <!-- res/drawable/battery_charging.xml -->
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        <!-- intrinsic size of the drawable -->
        android:height="24dp"
        android:width="24dp"
        <!-- size of the virtual canvas -->
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
       <group
             android:name="rotationGroup"
             android:pivotX="10.0"
             android:pivotY="10.0"
             android:rotation="15.0" >
          <path
            android:name="vect"
            android:fillColor="#FF000000"
            android:pathData="M15.67,4H14V2h-4v2H8.33C7.6,4 7,4.6 7,5.33V9h4.93L13,7v2h4V5.33C17,4.6 16.4,4 15.67,4z"
            android:fillAlpha=".3"/>
          <path
            android:name="draw"
            android:fillColor="#FF000000"
            android:pathData="M13,12.5h2L11,20v-5.5H9L11.93,9H7v11.67C7,21.4 7.6,22 8.33,22h7.33c0.74,0 1.34,-0.6 1.34,-1.33V9h-4v3.5z"/>
       </group>
    </vector>
    

此 XML 会渲染以下图片:

关于 AnimatedVectorDrawable 类

AnimatedVectorDrawable 会为矢量图形的属性添加动画。您可以将添加动画效果之后的矢量图形定义为三个单独的资源文件,也可以将其定义为可定义整个可绘制对象的单个 XML 文件。为了更好地理解,我们来看看这两种方法:多个 XML 文件单个 XML 文件

多个 XML 文件

借助这种方法,您可以定义三个单独的 XML 文件:

多个 XML 文件示例

以下 XML 文件演示了矢量图形的动画。

  • VectorDrawable 的 XML 文件:vd.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="vectorPath"
                 android:fillColor="#000000"
                 android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
           </group>
        </vector>
        
  • AnimatedVectorDrawable 的 XML 文件:avd.xml
  •     <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:drawable="@drawable/vd" >
             <target
                 android:name="rotationGroup"
                 android:animation="@anim/rotation" />
             <target
                 android:name="vectorPath"
                 android:animation="@anim/path_morph" />
        </animated-vector>
        
  • 用于 AnimatedVectorDrawable 的 XML 文件的 Animator XML 文件:rotation.xmlpath_morph.xml
  •     <objectAnimator
           android:duration="6000"
           android:propertyName="rotation"
           android:valueFrom="0"
           android:valueTo="360" />
        
        <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>
        

单个 XML 文件

借助这种方法,您可以通过 XML Bundle 格式将多个相关 XML 文件合并为单个 XML 文件。编译应用时,aapt 标记会创建单独的资源,并在添加动画效果之后的矢量中引用这些资源。此方法需要使用 Build Tools 24 或更高版本,且输出可向后兼容。

单个 XML 文件示例

    <animated-vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt">
        <aapt:attr name="android:drawable">
            <vector
                android:width="24dp"
                android:height="24dp"
                android:viewportWidth="24"
                android:viewportHeight="24">
                <path
                    android:name="root"
                    android:strokeWidth="2"
                    android:strokeLineCap="square"
                    android:strokeColor="?android:colorControlNormal"
                    android:pathData="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7" />
            </vector>
        </aapt:attr>
        <target android:name="root">
            <aapt:attr name="android:animation">
                <objectAnimator
                    android:propertyName="pathData"
                    android:valueFrom="M4.8,13.4 L9,17.6 M10.4,16.2 L19.6,7"
                    android:valueTo="M6.4,6.4 L17.6,17.6 M6.4,17.6 L17.6,6.4"
                    android:duration="300"
                    android:interpolator="@android:interpolator/fast_out_slow_in"
                    android:valueType="pathType" />
            </aapt:attr>
        </target>
    </animated-vector>
    

矢量可绘制对象向后兼容性解决方案

要在搭载的平台版本低于 Android 5.0(API 级别 21)的设备上支持矢量可绘制对象和添加动画效果之后的矢量可绘制对象,可通过 support-vector-drawableanimated-vector-drawable 这两个支持库分别获取 VectorDrawableCompatAnimatedVectorDrawableCompat

Android Studio 1.4 引入了对矢量可绘制对象的有限兼容性支持,具体方法是在编译时生成 PNG 文件。不过,矢量可绘制对象和添加动画效果之后的矢量可绘制对象支持库同时兼顾灵活性和广泛的兼容性 - 它们是支持库,因此您可以在 Android 2.1 及更高的平台版本(API 级别 7 及更高级别)上使用。要将您的应用配置为使用矢量支持库,请在应用模块的 build.gradle 文件中添加 vectorDrawables 元素。

使用以下代码段配置 vectorDrawables 元素:

    //For Gradle Plugin 2.0+
     android {
       defaultConfig {
         vectorDrawables.useSupportLibrary = true
        }
     }
    
    //For Gradle Plugin 1.5 or below
    android {
      defaultConfig {
        // Stops the Gradle plugin’s automatic rasterization of vectors
        generatedDensities = []
      }
      // Flag notifies aapt to keep the attribute IDs around
      aaptOptions {
        additionalParameters "--no-version-vectors"
      }
    }
     

您可以在搭载 Android 4.0(API 级别 14)及更高版本的所有设备上使用 VectorDrawableCompatAnimatedVectorDrawableCompat。关于 Android 加载可绘制对象的方式,并非所有接受可绘制对象 ID 的地方(例如 XML 文件中)都支持加载矢量可绘制对象。android.support.v7.appcompat 软件包中添加了很多功能,以便轻松使用矢量可绘制对象。首先,当您使用包含 ImageViewImageButtonFloatingActionButton 等子类的 android.support.v7.appcompat 软件包时,您可以使用新的 app:srcCompat 属性引用矢量可绘制对象以及任何其他可供 android:src 使用的可绘制对象:

    <ImageView
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:srcCompat="@drawable/ic_add" />
    

要在运行时更改可绘制对象,您可以像以前一样使用 setImageResource() 方法。要将矢量可绘制对象集成到您的应用中,使用 AppCompatapp:srcCompat 是最万无一失的方法。

支持库 25.4.0 及更高版本支持以下功能:

  • 路径变形(PathType 评估程序):用于将一个路径变为另一个路径。
  • 路径插值:用于定义灵活的插值器(表示为路径),而不是 LinearInterpolator 等系统定义的插值器。

支持库 26.0.0-beta1 及更高版本支持以下功能:

  • 沿路径移动:几何图形对象可以在动画中沿着任意路径来回移动。

使用支持库的多个 XML 文件的示例

以下 XML 文件演示了使用多个 XML 文件为矢量图形添加动画效果的方法。

  • VectorDrawable 的 XML 文件:vd.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="vectorPath"
                 android:fillColor="#000000"
                 android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
           </group>
        </vector>
        
  • AnimatedVectorDrawable 的 XML 文件:avd.xml
  •     <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
           android:drawable="@drawable/vd" >
             <target
                 android:name="rotationGroup"
                 android:animation="@anim/rotation" />
        </animated-vector>
        
  • 用于 AnimatedVectorDrawable 的 XML 文件的 Animator XML 文件:rotation.xml
  •     <objectAnimator
           android:duration="6000"
           android:propertyName="rotation"
           android:valueFrom="0"
           android:valueTo="360" />
        

单个 XML 文件

以下 XML 文件演示了使用单个 XML 文件为矢量图形添加动画效果的方法。编译应用时,aapt 标记会创建单独的资源,并在添加动画效果之后的矢量中引用这些资源。此方法需要使用 Build Tools 24 或更高版本,且输出可向后兼容。

使用支持库的单个 XML 文件的示例

    <animated-vector
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:aapt="http://schemas.android.com/aapt">
        <aapt:attr name="android:drawable">
            <vector xmlns:android="http://schemas.android.com/apk/res/android"
                android:width="64dp"
                android:height="64dp"
                android:viewportWidth="600"
                android:viewportHeight="600">
                <group
                    android:name="rotationGroup"
                    android:pivotX="300"
                    android:pivotY="300"
                    android:rotation="45.0" >
                    <path
                        android:name="vectorPath"
                        android:fillColor="#000000"
                        android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
                </group>
            </vector>
        </aapt:attr>
        <target android:name="rotationGroup">
            <aapt:attr name="android:animation">
                <objectAnimator
                    android:propertyName="rotation"
                    android:valueFrom="0"
                    android:valueTo="360"
                    android:duration="6000"
                    android:interpolator="@android:interpolator/fast_out_slow_in" />
            </aapt:attr>
        </target>
    </animated-vector>