Skip to content

Instantly share code, notes, and snippets.

@pgq10240817
Last active September 14, 2016 09:55
Show Gist options
  • Save pgq10240817/18acdb1c84bf9b142793562de1dcee0f to your computer and use it in GitHub Desktop.
Save pgq10240817/18acdb1c84bf9b142793562de1dcee0f to your computer and use it in GitHub Desktop.
AndroidVector - AnimatedVectorDrawable & VectorDrawable

Android--Vector


What is it ?

说到androidvector, 就要首先明白什么是Vector & SVG,

Vector: 矢量图形是计算机图形学中用点、直线或者多边形等基于数学方程的几何图元表示图像。矢量图形与使用像素表示图像的位图不同。 SVG: 是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式。SVG由W3C制定,是一个开放标准。

Why we use it ?

优点:

  • 占用空间小, 对比bitmap而言,天生具有优势
  • 放大不会出现失真现象, 完美适配

缺点:

  • 对设计师来讲, 学习导图工作成本增加了
  • 不适合复杂的图片(产出/时间投入比较高)

How we use it ?

0x01 定义一个vector

<vector xmlns:android="http://schemas.android.com/apk/res/android" 		
    android:width="24dp"
    android:height="24dp" 
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path android:name="path1"
          android:pathData="M24,0L0,24 M0,0L24,24z"
          android:strokeColor="#ff0000"
          android:strokeWidth="1"/>
</vector>

与之对应的SVG:

<?xml version="1.0" encoding="utf-8"?>
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
	<path d="M 24, 0 L 0,24" style="fill: none; stroke: red;"/>
    <path d="M 0, 0 L 24,24" style="fill: none; stroke: red;"/>
</svg>
  • width & height 定义了drawable大小
  • viewportWidth & viewportHeight 定义了了Vector画布大小
  • pathData定义了Vector的路径. 对应SVG文件的d属性

0x02 vector 命令说明

命令 参数 说明
M (x y)+ moveto 移动到
Z none  closepath 关闭路径
L (x y)+ lineto 连接到
H x+ horizontal lineto 水平线到 x+
V y+ vertical lineto 垂直线到 y+
C (x1 y1 x2 y2 x y)+ curveto  三次贝塞尔曲线到
S (x2 y2 x y)+ smooth curveto  光滑三次贝塞尔曲线到
Q (x1 y1 x y)+ uadratic Bézier curveto 二次贝塞尔曲线到
T (x y)+ smooth quadratic Bézier curveto 光滑二次贝塞尔曲线到
A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ elliptical arc  椭圆弧
R x1 y1 (x y)+ Catmull-Rom曲线
  • 其中M,Z比较好理解
  • L, H, V是除了M,Z最好用的指令.
  • C,S,Q,T是比较难理解,难用的指令, 本次一介绍Q,T为例
  • A,R 本次不做介绍

参考这篇文章介绍的更为生动详细点我

0x03 小试牛刀

掌握了0x02的一些基本命令后, 我们可以小试牛刀了....

1. 绘制

 <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
    <path android:name="path1"
          android:pathData="M6,18 L12,24 24,0"
          android:strokeColor="#ff0000"
          android:strokeWidth="1"/>
</vector>
2. 绘制

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
    <path android:name="path1"
          android:pathData="M12,12 L0,24 V0 H24 V24z"
          android:strokeColor="#ff0000"
          android:strokeLineJoin="round"
          android:strokeWidth="4"/>
</vector>

注意这里采用了fillColor填充整个path, 也可以同时设置strokeColor & strokeWidth来显示路径轮廓.

3. 绘制 带圆角的矩形 Q命令

Q命令式意图 enter image description here 对应的指令和参数是:

Q x1 y1, x y

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">
    <path android:name="path1"
          android:pathData="M0,4 Q0,0 4,0 H20 Q24,0 24,4 V20 Q24,24 20,24 H4 Q0,24 0,20Z"
          android:strokeColor="#ff0000"
          android:strokeLineJoin="round"
          android:strokeWidth="1"/>
</vector>

绘制思路 假设圆角为4

  1. 绘制左上角圆角 M0,4 Q,0 4,0
  2. 连线到右上角并且话圆角 H20 Q24,0 24,0 ....
4. 绘制 icon-smileQ, T命令

T命令式意图 enter image description here 对应的指令和参数是:

T x y

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportHeight="24.0"
        android:viewportWidth="24.0">

    <path
        android:name="pathEyeLeft"
        android:fillColor="#ff0000"
        android:pathData="M6,6 H8 V8 H6 V6Z"
    />
    <path
        android:name="pathEyerRight"
        android:fillColor="#ff0000"
        android:pathData="M16,6 H18 V8 H16 V6Z"
    />
    <path
        android:name="pathEyerMouth"
        android:pathData="M6,14 Q12,20 18,14"
        android:strokeColor="#ff0000"
        android:strokeWidth="1"
    />
    <path
        android:name="pathOutLine"
        android:pathData="M0,12 Q0,0 12,0 T 24,12 12,24 0,12"
        android:strokeColor="#ff0000"
        android:strokeWidth="1"/>

</vector>

外轮廓的圆

  <path
        android:name="pathOutLine"
        android:pathData="M0,12 Q0,0 12,0 T 24,12 12,24 0,12"
        android:strokeColor="#ff0000"
        android:strokeWidth="1"/>
5. 绘制 icon-smile A命令

对应的指令和参数是:

A rx ry x-axis-rotation large-arc-flag sweep-flag x y

参数 取值范围 说明
rx, ry double 半径
x-axis-rotation 度数 x轴旋转角度
large-arc-flag 0, 1 0表示小角度弧,1表示大角度
sweep-flag 0, 1 弧线方向,0逆时针,1沿顺时针
x, y double 圆弧的终点
<vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="200dp"
    android:height="200dp"
    android:viewportHeight="100"
    android:viewportWidth="100">
    <path
        android:fillColor="#ff0000"
        android:pathData="M2,50 A 48,48 0 1 0 98,50 A 48,48 0 1 0 2,50z"/>
</vector>

####参考: Markdown命令 SVG介绍

####0x00 准备工作


  1. svg-edit 在线编辑, 需要翻墙, Google推出
  2. Sketsa sketsa for windows sketsa for mac
  3. Adobe AI Adobe Illustrator cs6

####0x01 AnimatedVectorDrawable


1. AnimatedVectorDrawable 是什么 ?

AnimatedVectorDrawable uses ObjectAnimator and AnimatorSet to animate the properties of a VectorDrawable to create an animated drawable.

从官方文档看出AnimatedVectorDrawable 主要涉及了Animator & VectorDrawable 2个方面. 因此定义一个AnimatedVectorDrawable 一般需要3个xml文件.

2. 定义一个AnimatedVectorDrawable
2.1 定义VectorDrawable
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="200dp"
        android:height="200dp"
        android:viewportHeight="100"
        android:viewportWidth="100">

    <path
        android:name="v"
        android:pathData="M0,50 Q 50,0 100,50"
        android:strokeColor="#0000ff"
        android:strokeWidth="1"/>
</vector>

效果图: 效果图

期望动画后效果: 效果图

VectorDrawable 子节点可以定义group节点, 该节点功能用做 scale, rotate then translate动画.

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

上面的代码就定义了个group, 功能为旋转, 旋转路径需要在AnimatedVectorDrawable 设置

2.2 定义Animator
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M0,50 Q 50,0 100,50"
        android:valueTo="M0,50 Q 50,100 100,50"
        android:valueType="pathType"/>
</set>
2.3 定义AnimatedVectorDrawable
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_arc_unhappy">

    <target
        android:name="v"
        android:animation="@anim/animator_unhappy_2_happy"/>

</animated-vector>
2.4 设置drawable

首先设置View的drawable为定义的AnimatedVectorDrawable . 然后在进行业务处理, 按照以下方式启动动画.

			Drawable bgDrawable = view.getBackground();//或者其他
            if (bgDrawable instanceof Animatable) {
                ((Animatable) bg).start();
            }

这里需要注意的是Animator会指定VectorDrawable的动画属性, 上面例子指定的是pathData, 那么路径就会发生变化, 也可以指定strokeColor, strokeWidth, fillColor这些属性来设置动画.

例如上面的例子需要更改画笔颜色0xff0000ff->0xff00ff00, 那么Animator就一个如下:

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M0,50 Q 50,0 100,50"
        android:valueTo="M0,50 Q 50,100 100,50"
        android:valueType="pathType"/>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:propertyName="strokeColor"
        android:valueFrom="#0000ff"
        android:valueTo="#00ff00"/>
</set>



3. AnimatedVectorDrawable 官方例子

传送门

4. 其他例子, 包含了3官方例子

效果图, 效果图)

传送门

官方例子需要注意的有2个小点

  1. 形状路径动画
        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,0z"
参数 取值范围 说明
valueFrom 形状开始位置 三星形
valueTo 形状结束置 矩形
  1. AnimatedVectorDrawable 多个路径动画, 形状路径, 旋转路径)
<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>

####0x02 兼容性问题


2.1 Google官方法(有坑)
2.1.1. 配置gradle版本(2.0+), 1.5版本请参考传送门
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }  
2.1.2. 添加support包 (build.gradle)
 compile 'com.android.support:support-vector-drawable:24.0.0'
 compile 'com.android.support:animated-vector-drawable:24.0.0'
对应类 api要求 说明
support-vector-drawable vector 7+ 矢量图形
animated-vector-drawable animate-vector 11+ 动画矢量

如果只是需要显示矢量图形的话, 只需要添加support-vector-drawable即可. animated-vector-drawable对animate-vector的一些实现支持不全面 点我入坑

不支持的有如下(24.2.0下),

  • Path Morphing (PathType evaluator). This is used for morphing one path into another path.
  • Path Interpolation. This is used to defined a flexible interpolator (represented as a path) instead of the system defined ones like LinearInterpolator.
  • Move along path. This is rarely used. The geometry object can move around, along an arbitrary path.
    <objectAnimator
	    ....
        android:propertyName="pathData"
        android:valueFrom="M0,50 Q 50,0 100,50"
        android:valueTo="M0,50 Q 50,100 100,50"
        android:valueType="pathType"/>

类似这种的就不支持.(这个就是官方法的坑所在) 再api<21运行下回出现一个如下的FC:

    Caused by: android.content.res.Resources$NotFoundException: File *.xml from drawable resource ID #*
     ...
    Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #2: invalid drawable tag animated-vector
     ...

其实稍微好一点写法应该是这样:

gradle.properties 配置 android.support.version=24.0.0

build.gradle配置 final String supportVersion = project.property('android.support.version') compile 'com.android.support:support-vector-drawable:'+supportVersion compile 'com.android.support:animated-vector-drawable:'+supportVersion

这样的好处在与support版本发生变更的话, 比较容易更改.

2.1.3. Coding

#####2.1.3.1 ImageView, ImageButton设置drawable 在ImageView中使用app:srcCompat 来设置drawable对象 如果发现没用的话, 可以尝试用android.support.v7.widget.AppCompatImageView替换ImageView 或者继承 AppCompatActivity

#####2.1.3.2 Button, TextView ...设置Background

  1. 在Top Activity天剑下列静态域

static { AppCompatDelegate.setCompatVectorFromSourcesEnabled(true); }

  1. 声明包含vector的selector, View 设置selecor即可 P.S seletor中定义animated-vector会出现FC, 具体原因未知.
2.2 民间法

https://github.com/wnafee/vector-compat API:14+

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment