Android基础总结九:VectorDrawable

一、概述

Android 5.0系统中引入了VectorDrawable来支持矢量图(SVG),同时还引入了AnimatedVectorDrawable来支持矢量图动画。由于兼容性问题,所以到目前使用矢量图的应用还是比较少。关于SVG的知识可以参考:SVG 教程

二、VectorDrawable的优缺点

优点:

• Vector图像可以自动进行适配,不需要通过分辨率来设置不同的图片
• Vector图像可以大幅减少图像的体积,同样一张图,用Vector来实现,可能只有PNG的几十分之一
• 使用简单,很多设计工具,都可以直接导出SVG图像,从而转换成Vector图像
• 功能强大,不用写很多代码就可以实现非常复杂的动画
• 成熟、稳定,前端已经非常广泛的进行使用了

缺点:

• 没有位图表达的色彩丰富

三、一些相关链接

1.http://inloop.github.io/svg2android/ 一个非常牛逼的网站,可以在线将普通图像转换为Android Vector Drawable
2.http://editor.method.ac/ SVG编辑器
3.http://www.iconfont.cn/ 阿里巴巴UX矢量库,可以下载SVG PNG格式的icon

三、VectorDrawable的使用说明

VectorDrawable并没有支持所有SVG规范,目前只支持PathData和有限的Group功能,另外还有一个clip-path属性来支持后面绘图的区域。

所以对于使用 VectorDrawable 而言,我们只需要了解 SVG 的 PathData 规范即可。通过查看 PathData文档,可以看到 path 数据包含了一些绘图命令,比如 :

  • moveto 命令 M or m ,移动到新的位置 (大写的命令为绝对坐标命令;小写的命令为相对坐标命令, 下同)

  • closepath 命令 Z or z,封闭路径,从当前的位置画一条直线到该路径或者子路径起始位置

  • lineto 命令 L or l,从当前的位置画一条线到指定的位置

  • horizontal lineto 命令 H or h,水平画一条直线到指定位置

  • vertical lineto 命令 V or v,垂直画一条直线到指定位置

  • … 还有很多其他命令,详情请参考文档

在 文档中有个绘制三角形的示例:

XHTML

<svg width="4cm" height="4cm" viewBox="0 0 400 400"
     xmlns="http://www.w3.org/2000/svg" version="1.1">
  <rect x="1" y="1" width="398" height="398"
        fill="none" stroke="blue" />
  <path d="M 100 100 L 300 100 L 200 300 z"
        fill="red" stroke="blue" stroke-width="3" />
</svg>

该示例的画布大小为 400 X 400像素(左上角坐标为0,0; 右下角坐标为400,400), path 路径为: 移动到 100、100 位置,然后画一条线到绝对坐标 300、100位置,然后画一条线到绝对坐标 200、300位置,然后画一条线到该路径的起始位置。这样一个倒三角形就绘制出来了。

只需要把上面的 path 路径中的数据放到 VectorDrawable 定义xml文件中,就可以实现一个 Android 版本的 矢量图了。例如 在 drawable 目录中创建一个 triangle.xml 文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <path
        android:pathData="M 100 100 L 300 100 L 200 300 z"
        android:strokeColor="#000000"
        android:strokeWidth="5"
        android:fillColor="#FF0000"
        />
</vector>

需要注意的是, 在根元素 vector 上有两个宽高设置,其中 viewport 是指矢量图里面的画布大小,而android:width 和 android:height 是指该矢量图所对应的 VectorDrawable 的大小。
根元素vector的属性如下:

属性取值功能
android:name定义该drawable的名字
android:width定义该 drawable 的内部(intrinsic)宽度,支持所有 Android 系统支持的尺寸,通常使用 dp
android:height定义该 drawable 的内部(intrinsic)高度,支持所有 Android 系统支持的尺寸,通常使用 dp
android:viewportWidth定义矢量图视图的宽度,视图就是矢量图 path 路径数据所绘制的虚拟画布
android:viewportHeight定义矢量图视图的高度,视图就是矢量图 path 路径数据所绘制的虚拟画布
android:tint定义该 drawable 的 tint 颜色。默认是没有 tint 颜色的
android:tintMode定义 tint 颜色的 Porter-Duff blending 模式,默认值为 src_in
android:autoMirrored设置当系统为 RTL (right-to-left) 布局的时候,是否自动镜像该图片。比如 阿拉伯语。
android:alpha该图片的透明度属性

path 元素里面的 pathData 就是矢量图的路径数据,除此之外还可以设置其他属性。 path 元素一共包含如下属性:

属性取值功能
android:name定义该 path 的名字,这样在其他地方可以通过名字来引用这个路径
android:pathDataSVG 中 d 元素一样的路径信息
android:fillColor定义填充路径的颜色,如果没有定义则不填充路径
android:strokeColor定义如何绘制路径边框,如果没有定义则不显示边框
android:strokeWidth定义路径边框的粗细尺寸
android:strokeAlpha定义路径边框的透明度
android:fillAlpha定义填充路径颜色的透明度
android:trimPathStart0~1从路径起始位置截断路径的比率
android:trimPathEnd0~1从路径结束位置截断路径的比率
android:trimPathOffset0~1设置路径截取的范围
android:strokeLineCapbutt, round, square设置路径线帽的形状
android:strokeLineJoinmiter,round,bevel设置路径交界处的连接方式
android:strokeMiterLimitbutt, round, square设置斜角的上限



拿android:trimPathStart举个例子:
画一条直线:

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

    <path
        android:name="line"
        android:pathData="M5.705,5.705 L18.295,5.705"
        android:strokeColor="#000000"
        android:strokeWidth="2"
        android:trimPathStart="0"/>
</vector>

设置android:trimPathStart="0"效果如下:

这里写图片描述

设置android:trimPathStart="0.5"将会截掉直线的前半段,只显示后半段:

这里写图片描述

有时候我们需要对几个路径一起处理,这样就可以使用 group 元素来把多个 path 放到一起。 group 支持的属性如下:

属性取值功能
android:name定义 group 的名字
android:rotationSVG 中 d 元素一样的路径信息
android:pivotX定义缩放和旋转该 group 时候的 X 参考点。该值相对于 vector 的 viewport 值来指定的。
android:pivotY定义缩放和旋转该 group 时候的 Y 参考点。该值相对于 vector 的 viewport 值来指定的。
android:scaleX定义 X 轴的缩放倍数
android:scaleY定义 Y 轴的缩放倍数
android:translateX定义移动 X 轴的位移。相对于 vector 的 viewport 值来指定的。
android:translateY定义移动 Y 轴的位移。相对于 vector 的 viewport 值来指定的。

通过上面的属性可以看出, group 主要是用来设置路径做动画的关键属性的。

最后, vector 还支持 clip-path 元素。定义当前绘制的剪切路径。注意,clip-path 只对当前的 group 和子 group 有效。

属性取值功能
android:name定义 clip path 的名字
android:pathData同path

从上面 vector 支持的属性可以看出,功能还是比较丰富的。例如 前面提到的三角形,通过 group 可以把其旋转 90度。

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="400dp"
    android:height="400dp"
    android:viewportHeight="400"
    android:viewportWidth="400">
    <group
        android:name="name"
        android:pivotX="200"
        android:pivotY="200"
        android:rotation="90">
        <path
            android:fillColor="#FF0000"
            android:pathData="M 100 100 L 300 100 L 200 300 z"
            android:strokeColor="#000000"
            android:strokeWidth="5" />
    </group>
</vector>

四、兼容性

android L 以后矢量图是以VectorDrawable的形式来使用了, 但是这个库只支持L以后的,于是谷歌在AppCompat 23.2出了一个兼容包( VectorDrawableCompat,AnimatedVectorDrawableCompat),也就是说,Vector可以使用于Android 2.1以上的所有系统,只需要:
1.引用com.android.support:appcompat-v7:23.2.0以上的版本
2.对于Gradle Plugin 2.0以上:

android {

    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

用Gradle Plugin 2.0以下,Gradle Plugin 1.5以上:

android {
  defaultConfig {
    // Stops the Gradle plugin’s automatic rasterization of vectors
    generatedDensities = []
  }
  // Flag to tell aapt to keep the attribute ids around
  aaptOptions {
    additionalParameters "--no-version-vectors"
  }
}

另外还需要应该注意以下几点:

1 . ImageView\ImageButton中使用(Activity继承自AppCompatActivity,如果不是,请使用AppCompatImageView)
对于ImageView这样的控件,要兼容Vector图像,只需要将之前的android:src属性,换成app:srcCompat即可,示例代码如下所示:

<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/vector_image"/>

在代码中设置的话,可以使用setBackgroundResource方法设置,代码如下所示:

ImageView iv = (ImageView) findViewById(R.id.iv);
iv.setImageResource(R.drawable.vector_image);

2 . 当在非ImageView控件中(Button、TextView等)作为Background、CompoundDrawable时,需要在Activity中加入以下声明

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

另外,如果直接在xml布局文件中使用,则必须使用selector、layer-list这种容器包裹起来,不能直接使用
(在代码中设置不需要)

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/vector_retry" />
</layer-list>

3 . 虽然Google已经对Vector图像进行了Android 2.1以上的兼容,但对于动态Vector动画,还是有很多限制的,例如:
1) Path Morphing,即路径变换动画,在Android pre-L版本下是无法使用的(不会动)。
2)Path Interpolation,即路径插值器,在Android pre-L版本只能使用系统的插值器,不能自定义。
3)Path Animation,即路径动画,这个一般使用贝塞尔曲线来代替,所以没有太大影响。

4 . 除了在低版本上的兼容性问题,在L版本以上,也存在兼容性问题,即继承了AppCompatActivity的界面,如果直接设置ImageView的srcCompat,那么Path Morphing动画是无法生效的,因为默认的AppCompatActivity已经默认使用ImageViewCompat给转换了,但是AnimatedVectorDrawableCompat是不支持Path Morphing动画的,所以,在AppCompatActivity界面里面就无效了。

解决办法很简单,即使用代码来给ImageView添加动画:

ImageView imageView = (ImageView) view;
AnimatedVectorDrawable morphing = (AnimatedVectorDrawable)getDrawable(morphing);
imageView.setImageDrawable(morphing);
if (morphing != null) {
    morphing.start();
}

注意不要使用AnimatedVectorDrawableCompat。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值