Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
sofina edited this page Feb 10, 2017 · 11 revisions

####什么是Vector Drawable:

矢量图区别于我们平时使用的位图(png,jpg等),位图是由一个单元一个单元的像素组成的,在大分辨率的手机上,图片会被拉伸,导致其显示模糊。而矢量图是由点,线,矩形,圆,弧线等绘制而成的,学会了它,我们可以自己来画一些简单的icon,甚至做一些简单的动画。

优点:

1, 它不会因为图像的缩放而失真。在安卓开发中也就意味着你不需要为不同分辨率的设备定义不同大小的图片资源;

2,可以减小包大小,同样一张图,用vector实现,大小仅为png图片的十分之一;

3,功能强大,所有复杂的动画都不需要用java代码实现,只需要在xml文件里编辑即可;

4,动画执行流畅,优美,android5.0以上的开机动画就使用animated vector drawable实现;

5,成熟、稳定,前端已经非常广泛的进行使用了。

####兼容问题

android 5.0以上已经完美支持vector drawable ,无需适配

android 5.0以下的版本,需要在build.gradle中做如下改动

一,gradle 版本是 2.0 以上,

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

二, gradle plugin V1.5及以上,2.0 以下的版本

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
    generatedDensities = ['hdpi', 'xhdpi']//生成的png图片密度
  }
  aaptOptions {
    additionalParameters "--no-version-vectors"//这是为了让aapt给生成的png资源保留resource id,否则运行会发生ResourceNotFoundException异常
  }
}

并且需要添加appCompat 的支持

compile 'com.android.support:appcompat-v7:23.4.0'

以上这两种方式,都会在编译阶段,将vector 转化成png资源来使用。

####如何生成一个vector 资源?

方式一,自己写

pathData的命令是极为繁琐,可读性很差的,他的命令可能是这样的

    <path
        android:fillColor="#FF000000"
        android:pathData="M12,2 C6.48,2 2,6.48 2,12 s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>

也有可能是这样的

      <path
        android:fillColor="#FF000000"
        android:pathData="M7.52,21.48C4.25,19.94 1.91,16.76 1.55,13L0.05,13C0.56,19.16 5.71,24 12,24l0.66,-0.03 -3.81,-3.81 -1.33,1.32zM8.41,14.96c-0.19,0 -0.37,-0.03 -0.52,-0.08 -0.16,-0.06 -0.29,-0.13 -0.4,-0.24 -0.11,-0.1 -0.2,-0.22 -0.26,-0.37 -0.06,-0.14 -0.09,-0.3 -0.09,-0.47h-1.3c0,0.36 0.07,0.68 0.21,0.95 0.14,0.27 0.33,0.5 0.56,0.69 0.24,0.18 0.51,0.32 0.82,0.41 0.3,0.1 0.62,0.15 0.96,0.15 0.37,0 0.72,-0.05 1.03,-0.15 0.32,-0.1 0.6,-0.25 0.83,-0.44s0.42,-0.43 0.55,-0.72c0.13,-0.29 0.2,-0.61 0.2,-0.97 0,-0.19 -0.02,-0.38 -0.07,-0.56 -0.05,-0.18 -0.12,-0.35 -0.23,-0.51 -0.1,-0.16 -0.24,-0.3 -0.4,-0.43 -0.17,-0.13 -0.37,-0.23 -0.61,-0.31 0.2,-0.09 0.37,-0.2 0.52,-0.33 0.15,-0.13 0.27,-0.27 0.37,-0.42 0.1,-0.15 0.17,-0.3 0.22,-0.46 0.05,-0.16 0.07,-0.32 0.07,-0.48 0,-0.36 -0.06,-0.68 -0.18,-0.96 -0.12,-0.28 -0.29,-0.51 -0.51,-0.69 -0.2,-0.19 -0.47,-0.33 -0.77,-0.43C9.1,8.05 8.76,8 8.39,8c-0.36,0 -0.69,0.05 -1,0.16 -0.3,0.11 -0.57,0.26 -0.79,0.45 -0.21,0.19 -0.38,0.41 -0.51,0.67 -0.12,0.26 -0.18,0.54 -0.18,0.85h1.3c0,-0.17 0.03,-0.32 0.09,-0.45s0.14,-0.25 0.25,-0.34c0.11,-0.09 0.23,-0.17 0.38,-0.22 0.15,-0.05 0.3,-0.08 0.48,-0.08 0.4,0 0.7,0.1 0.89,0.31 0.19,0.2 0.29,0.49 0.29,0.86 0,0.18 -0.03,0.34 -0.08,0.49 -0.05,0.15 -0.14,0.27 -0.25,0.37 -0.11,0.1 -0.25,0.18 -0.41,0.24 -0.16,0.06 -0.36,0.09 -0.58,0.09L7.5,11.4v1.03h0.77c0.22,0 0.42,0.02 0.6,0.07s0.33,0.13 0.45,0.23c0.12,0.11 0.22,0.24 0.29,0.4 0.07,0.16 0.1,0.35 0.1,0.57 0,0.41 -0.12,0.72 -0.35,0.93 -0.23,0.23 -0.55,0.33 -0.95,0.33zM16.96,9.04c-0.32,-0.33 -0.7,-0.59 -1.14,-0.77 -0.43,-0.18 -0.92,-0.27 -1.46,-0.27L12,8v8h2.3c0.55,0 1.06,-0.09 1.51,-0.27 0.45,-0.18 0.84,-0.43 1.16,-0.76 0.32,-0.33 0.57,-0.73 0.74,-1.19 0.17,-0.47 0.26,-0.99 0.26,-1.57v-0.4c0,-0.58 -0.09,-1.1 -0.26,-1.57 -0.18,-0.47 -0.43,-0.87 -0.75,-1.2zM16.57,12.2c0,0.42 -0.05,0.79 -0.14,1.13 -0.1,0.33 -0.24,0.62 -0.43,0.85 -0.19,0.23 -0.43,0.41 -0.71,0.53 -0.29,0.12 -0.62,0.18 -0.99,0.18h-0.91L13.39,9.12h0.97c0.72,0 1.27,0.23 1.64,0.69 0.38,0.46 0.57,1.12 0.57,1.99v0.4zM12,0l-0.66,0.03 3.81,3.81 1.33,-1.33c3.27,1.55 5.61,4.72 5.96,8.48h1.5C23.44,4.84 18.29,0 12,0z"/>

所以,除非是很简单的图形,比如一个圆,或者一个方形,否则不建议使用这种方式生成vector资源

方式二,用android studio提供的现成的资源,这些资源都很简单,而且很多都不太实用

首先在drawable 目录下new 一个 vector 资源

选一张你喜欢的图片,然后ok next finish…… 即可

方式三,用svg资源生成

在方式二的第二步选择

这里有很多现成的svg资源 ,如果还是没有你喜欢的,那么只能叫设计师给你切个图了 这是最简单也是最实用的方式,但是首先你得有设计师~

####基本语法介绍:

以下这些命令都有大小写,大写表示绝对位置,小写表示相对位置

M x,y or m x,y:移动绘制点到指定位置, 后面可能跟不止一对坐标, 如果跟多对则隐式的代表在这些点之间画线.

Z or z: 在开始点与结束点之间画一条线. 后面不需要跟任何参数.

L x,y or l(我是L的小写,不是1) x,y: 在当前点与点(x,y)之间画直线.

H x or h x: 水平画线: 在当前点与横坐标X之间画一条水平线.

V y or v y: 垂直画线: 在当前点与纵坐标Y之间画一条竖直线.

以上这些指令比较简单,有了这些,我们就可以画一个简单的方形了

  <?xml version="1.0" encoding="utf-8"?>
  <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="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M12,12 L24,12 L24,24 L12,24 z" />

</vector>

那么要如何画圆弧呢?

圆弧的命令稍微复杂一些,理解它首先需要理解贝塞尔曲线

Q x0,y0 x1,y1 or q x0,y0 x1,y1 : [二次贝塞尔曲线] 第一个数据点是当前点,x0,y0 是控制点,x1,y1是第二个数据点。

绘制一条简单的二次贝塞尔曲线:

   <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="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M12,12 Q24,12 24,24  " />

</vector>

C x0,y0 x1,y1 x2,y2 or c x0,y0 x1,y1 x2,y2: [三次贝塞尔曲线] 第一个数据点是当前点,x0,y0 x1,y1是两个控制点,x2,y2是第二个数据点。

绘制一条简单的三次贝塞尔曲线:

   <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="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M12,12 C24,12 12,24 24,24  " />

</vector>

A rx,ry x-axis-rotation large-arc-flag,sweepflag dx,dy a rx,ry x-axis-rotation large-arc-flag,sweepflag dx,dy

弧线:弧线的指令比上述几种都复杂, rx ry 表示水平方向和垂直方向的半径,x-axis-rotation 表示水平方向的旋转角度,large-arc-flag,sweepflag 有4中组合,分别为0,0、 0,1、 1,0 和 1,1 , dx dy 表示终点距离;其中4种组合产生的效果为

有了这些,我们呢就可以画圆了

   <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="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M2,12 a10,10 0 1,1 20,0 a10,10 0 1,1 -20 0" />

</vector>

####怎么用Vector Drawable做一个简单的动画?? 定义一个animated vector drawable 只需要简单的三步:

1)在 res/drawable/ 目录下 创建一个vector drawable 文件demo_drawable.xml;

假设我们画一个圆, 并且定义一个叫做 tick 的path,之后需要对这个tick做动画

   <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="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M2,12 a10,10 0 1,1 20,0 a10,10 0 1,1 -20 0" />

     <path
        android:name="tick"
        android:pathData="M6,11 l5,4 l7,-7"
        android:strokeAlpha="1"
        android:strokeColor="@color/colorAccent"
        android:strokeWidth="1" />

</vector>

2)在res/anim/ 目录下, 创建一个动画文件demo_anim.xml

这个文件中,定义一个画对勾的动画,第一个objectAnimator 画勾的短边,第二个画勾的长边

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:ordering="sequentially"
    android:shareInterpolator="false">

    <objectAnimator
        android:duration="500"
        android:propertyName="pathData"  //只针对 tick 中的 pathData属性 做动画
        android:valueFrom="M6,11 l0,0 l0,0" //pathData 的绘制起点
        android:valueTo="M6,11 l3.5,4 l0,0"//pathData 的绘制终点
        android:valueType="pathType" /> //pathData 值的类型

    <objectAnimator
        android:duration="500"
        android:propertyName="pathData"
        android:valueFrom="M6,11 l3.5,4 l0,0"
        android:valueTo="M6,11 l3.5,4 l8,-7"
        android:valueType="pathType" />
</set>
  1. 在 res/drawable/ 目录下创建一个文件 demo.xml,用于指定demo_drawable 中的tick对象 执行 demo_anim 中画对勾动画
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/demo_drawable"> //这就是第一步创建的drawable文件

    <target
        android:animation="@anim/demo_anim" //这是第二步创建的动画文件
        android:name="tick"/>// 指定tick 执行此动画

</animated-vector>

最后在代码中加载该demo 并 调用start()方法即可成功执行动画。

        AnimatedVectorDrawable mDrawable = (AnimatedVectorDrawable) getDrawable(R.drawable.demo);//加载demo
        imageView.setImageDrawable(mDrawable);
        mDrawable.start();

一个简单的对勾动画就做好了

用vector drawable 画的一些简单的动画demo,挺好玩的,github地址

####性能问题

  1. 和png的绘制效率有一个平衡点,当vector比较简单时,绘制效率比png图片高,越复杂的path,绘制时间越长,渲染时间也越长。

  2. 严格控制适量图的大小,因为越大的图片占用的内存越多

  3. 不要做过于复杂和时间太长的动画,因为vector在GPU中没有缓存,所以不能进行重绘。

####开发建议

1)能使用shape 画的icon,不要使用vector drawable 画,因为shape绘制简单,而且渲染更快

画一个圆角矩形 使用shape 完成

<shape xmlns:android="http://schemas.android.com/apk/res/android"
 android:shape="rectangle">
 <solid
     android:color="@color/colorAccent"/>
 <corners android:radius="5dp"/>
</shape>

使用vector完成

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="20dp"
    android:height="20dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:name="circle"
        android:fillColor="@color/colorPrimary"
        android:pathData="M0,5
        a5,5 0 0,1 5,-5
        l14,0
        a5,5 0, 0,1 5,5
        l0,14
        a5,5 0 0,1, -5,5
        l-14,0
        a5,5 0 0,1 -5,-5z" />

</vector>

2)清理大师工程里,不要给vector 添加动画,因为5.0以下设备在编译的时候就把vector drawable转成png资源,这只是一张静态图片

3)清理大师里,简单地icon如,列表前面地icon 都可以用vector drawable 实现。

例:用vector drawable实现软件管理的icon

<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="circle"
        android:fillColor="#e69310"
        android:pathData="M0,5
        a5,5 0 0,1 5,-5
        l14,0
        a5,5 0, 0,1 5,5
        l0,14
        a5,5 0 0,1, -5,5
        l-14,0
        a5,5 0 0,1 -5,-5z" />

    <path
        android:fillColor="@android:color/white"
        android:pathData="M11,11
        l-3,0
        a3,3 0 1,1 3,-3 z" />

    <path
        android:fillColor="@android:color/white"
        android:pathData="M13,11
        l3,0
        a3,3 0 1,0 -3,-3z" />

    <path
        android:fillColor="@android:color/white"
        android:pathData="M11,13
        l-3,0
        a3,3 0 1,0 3,3z" />

    <path
        android:fillColor="@android:color/white"
        android:pathData="M13,13
        l3,0
        a3,3 0 1,1 -3,3z" />

</vector>

Clone this wiki locally

Morty Proxy This is a proxified and sanitized view of the page, visit original site.