Vector标签解析

本文深入探讨Android中的Vector Drawable,从SVG的优势、语法介绍到动态Vector的实现,涵盖Vector的使用前言、Path指令解析、转换设计、Android Studio设计支持以及动态Vector的动画原理和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vector使用前言

如果要说Vector,就不得不提SVG了,首先,需要讲解两个概念——SVG和Vector。

SVG,即Scalable Vector Graphics 矢量图,这种图像格式在前端中已经使用的非常广泛了。

Vector,在Android中指的是Vector Drawable,也就是Android中的矢量图,因此,可以说Vector就是Android中的SVG实现,因为Android中的Vector并不是支持全部的SVG语法,也没有必要,因为完整的SVG语法是非常复杂的,但已经支持的SVG语法已经够用了,特别是Path语法,几乎是Android中Vector的标配。

更多SVG的介绍,可以看我的另一篇博客Android里的SVG,这里就不对SVG作过多介绍了。

Vector优势

Vector Drawable相对于普通的Drawable来说,有以下几个好处:

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

Vetor语法介绍

Android以一种简化的方式对SVG进行了兼容,这种方式就是通过使用它的Path标签,通过Path标签,几乎可以实现SVG中的其它所有标签。

Path指令解析如下所示:

1.支持的指令:

M = moveto(M X,Y) :相当于 Android Path 里的moveTo(),用于移动起始点
L = lineto(L X,Y): 相当于 android Path 里的lineTo(),用于画线
H = horizontal lineto(H X):画水平线到指定的X坐标位置
V = vertical lineto(V Y):画垂直线到指定的Y坐标位置
C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY): 相当于cubicTo(),三次贝塞尔曲线
S = smooth curveto(S X2,Y2,ENDX,ENDY) : 同样三次贝塞尔曲线,更平滑
Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY): quadTo(),二次贝塞尔曲线
T = smooth quadratic Belzier curveto(T ENDX,ENDY): 同样二次贝塞尔曲线,更平滑
A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y): 相当于arcTo(),用于画弧
Z = closepath 相当于closeTo(),关闭path

同样的说明,我的那篇博客Android里的SVG也有介绍。

2.使用原则:

  • 坐标轴为以(0,0)为中心,X轴水平向右,Y轴水平向下
  • 所有指令大小写均可。大写绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系
  • 指令和数据间的空格可以省略
  • 同一指令出现多次可以只用一个

SVG的各种转换设计

要从一般使用的PNG图像转换到SVG图像,对于设计师来说,并不是一件难事,因为大部分的设计工具(PS、Illustrator等等)都支持导出各种格式的图像,如PNG、JPG,当然,也包括SVG,因此,设计师可以完全按照原有的方式进行设计,只是最后导出的时候,选择SVG即可。

不要求开发者都去学习使用这些设计工具,开发者可以利用一些工具,自己转换一些比较基础的图像,Android SVG to VectorDrawable 可以在线将普通图像转换为Android Vector Drawable。如图所示:

至于SVG的编辑器,我在Android里的SVG中详细说明了,有兴趣的可以看看。

Android Studio设计

利用Android Studio的Vector Asset,可以非常方便的创建Vector图像,甚至可以直接通过本地的SVG图像来生成Vector图像,系统自带的图片也很丰富。如图所示:

Vector图像

一个Vector图像,同样是一个xml文件,在这里我用一个基本的Vector图像来介绍一下:

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

    <path android:fillColor="#0000ff"
        android:pathData="M20.5, 9.5
        c-1.955, 0, -3.83, 1.268, -4.5, 3
        c-0.63, -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>

这个Vector图像的效果是一个心型图案

现在来解释这几个标签:

  • android:width :定义图片的宽
  • android:height:定义图片的高
  • android:viewportHeight 定义图像高被划分的比例大小,例如例子中的32,即把256dp大小的图像划分成32份,后面Path标签中的坐标,就全部使用的是这里划分后的坐标系统。
  • android:viewportWidth:定义图像宽被划分的比例大小,效果与viewportHeight一样。这样做有一个非常好的作用,就是将图像大小与图像分离,后面可以随意修改图像大小,而不需要修改PathData中的坐标。
  • android:fillColor: 设置绘制的图形中用什么颜色填充
  • android:PathData: 这里就用了SVG中的path指令绘制路径。

动态Vector

动态Vector才是Android Vector Drawable的精髓所在

每个Vector动画,基本都包含四部分内容,即:

  • Vector:图像资源
  • Animated-vector:动画、图像粘合剂
  • ObjectAnimator:动画资源
  • 代码:启动动画

动态的Vector需要通过animated-vector标签来进行实现,它就像一个粘合剂,将控件与Vector图像粘合在了一起,我们在这里实现一个时钟的小例子:

既然我们要实现时钟的动画,我们首先需要一个时钟的图形,所以在drawable目录下新建一个clock.xml,然后分别绘制分针,时针和表盘。

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

    <!--绘制分针-->
    <group
        android:name="minutes"
        android:pivotX="50"
        android:pivotY="50"
        android:rotation="0">
        <path android:strokeColor="@android:color/holo_green_dark"
            android:strokeLineCap="round"
            android:strokeWidth="1.5"
            android:pathData="M 50, 50, L 50, 12"/>
    </group>
    <!-- 绘制时针 -->
    <group
        android:name="hours"
        android:pivotX="50"
        android:pivotY="50"
        android:rotation="0">
        <path android:strokeColor="@android:color/holo_blue_dark"
            android:strokeLineCap="round"
            android:strokeWidth="1"
            android:pathData="M 50, 50, L 24, 50"/>
    </group>
    <!-- 绘制表盘 -->
    <path android:strokeColor="@android:color/holo_red_dark"
        android:strokeWidth="1"
        android:pathData="@string/path_circle"/>
</vector>

这里出现了几个新的标签和属性,pivotX和pivotY表示缩放的中轴点坐标,距离自身左边缘的位置。我们这里就是指针绕中点旋转。
stroke在我的博客Android里的SVG中有说明。

而path_circle是我在strings.xml中定义的变量,可以绘制出一个圆。

    <string name="path_circle">
        M 50, 50
        m -48, 0
        a 48, 48 0 1, 0 96, 0
        a 48, 48 0 1, 0 -96, 0
    </string>

接着我们还需要为我们的时针和分针设置动画,在animator文件夹下创建hour.xml和minute.xml两个文件。

hour.xml:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="8000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="240"
    android:interpolator="@android:anim/linear_interpolator"
    />

minute.xml:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360"
    android:repeatCount="7"
    android:interpolator="@android:anim/linear_interpolator"
    />

linear_interpolator是线性插值器,在我的博客 Android动画–Interpolator的介绍中详细说明了。

时针代码的含义是在8秒钟从0度旋转到240度。
分针代码的含义是每过一秒旋转一周,旋转8次。

现在就是我们的animated-vector了,anim_clock.xml:

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/clock">

    <!-- 用于控制时针的旋转 -->
    <target
        android:animation="@animator/hour"
        android:name="hours"/>

    <!-- 用于控制分针的旋转 -->
    <target
        android:animation="@animator/minute"
        android:name="minutes"/>

</animated-vector>

这样就帮我们的时针和分针设置好动画了。
接下来就是测试了,把anim_clock.xml添加到ImageView中。写一个animate()方法:

    private void animate() {
        Drawable drawable = mImageView.getDrawable();
        if (drawable instanceof Animatable) {
            ((Animatable) drawable).start();
        }
    }

在mImageView的监听事件中调用animate(),运行。

结束语:本文仅用来学习记录,参考查阅。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值