此篇是 Understanding VectorDrawable pathData commands in Android 的译文, 如有疑问请查看原文.
打开任何VectorDrawable XML文件,您会在pathData属性中遇到一些神秘的命令。
<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="v"
android:fillColor="#000000"
android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
</group>
</vector>
那些定期使用Paths的人可能能够解释这个命令并告诉你它的形状。对于我们其他人来说,这可能有点神秘
什么是VectorDrawable
VectorDrawable是Vector的XML表示。与流行的图像格式(如Bitmap,JPEG,GIF和PNG)不同,Vector在放大或缩小时不会丢失质量。这样就不需要捆绑不同密度的图像,因此可以节省大量的APK膨胀。实际上,VectorDrawables包含路径命令(如何绘制直线和圆弧),就像使用Canvas时的路径命令一样,绘制和渲染VectorDrawables是时间和内存消耗过程,这就是为什么VectorDrawable最适合用于简单的平面图形。
为什么还要理解这些命令呢?我只是把它们作为SVG!
如果您希望为VectorDrawable设置动画,就像现在所有的愤怒一样,其中一个要求是您要动画的VectorDrawable应该共享相同数量的命令。此外,有助于了解这些命令中的每一个将如何导致图形移动/更改以使图像动画化。为此,了解这些路径命令的含义可能会有很大帮助。
了解pathData命令
首先我要说的是,无论你学习道路命令多少,除非你是一个天才,否则你所能理解的内容将受到限制。矢量图形程序并不具备干净和人类可读的代码作为高优先级。像SVG这样的矢量图形文件通过Android Studios VectorDrawable生成器传输之后,它们变得更加清晰和易于阅读,但是,我发现很多命令仍然可能比你需要的更复杂。然后要了解圆圈和圆弧只需要你有很多想象力或一些严肃的数学实力。
基础
基本路径命令由字母表后跟一个或多个数字组成。这些数字通常以逗号分隔,但不一定是。例如
M100,100 L300,100 L200,300 z
//或
M 100 100 L 300 100 L 200 300 z
//或
M110,100L300,100L200,300z
字母表可以是大写或小写。大写表示绝对位置,小写表示相对位置。
命令
M或m(X,Y)+
moveto:将光标移动到位置,大写是绝对的,小写是相对移动
命令后跟X,Y坐标。M命令后面可以有多组坐标,这些坐标被视为隐式lineto命令。
Z或z
closepath:从光标的当前位置到路径的起始位置绘制一条线。没有任何参数。
L或l (X,Y)+
lineto:从当前位置到X,Y指定的位置绘制一条线。大写表示绝对坐标,小写表示相对坐标。您可以在lineto命令后面有多组坐标。如果要指定多个坐标集,则表示您正在创建折线(由多个字符串线组成的形状)。
H或h(X)+
水平线从当前光标位置到X指定的位置绘制一条水平线。如果命令后面有多个X坐标,则将其视为折线。Y坐标保持不变。大写字母H是绝对坐标,小写字母h是相对坐标。
V或V(Y)+
立式了lineTo绘制一条从当前光标位置到由规定的Y.如果有命令以下多个Y坐标位置,这将被视为一个多段线的垂直线。X坐标保持不变。大写字母V是绝对坐标,小写字母v是相对坐标。
例
考虑到这一点,让我们解释一下上面的命令:
M100,100 L300,100 L200,300 z
M100,100:将光标移动到绝对坐标X = 100 Y = 100px。
L300,100:画一条线到X = 300 Y = 100(起始位置是100,100)。
L200,300:画一条线到X = 200 Y = 300(起始位置是300,100)。
z:关闭路径,从当前位置到100,100的直线。当您关闭路径时,将使用指定的填充颜色填充形状。如果你的形状不需要关闭,你可以把它留下来,比如复选标记或十字形。
如果我们勾勒出来,你会注意到形状是一个颠倒的三角形!
如果我们将它放在一个简单的VectorDrawable XML中,我们可以看到结果:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
<!-- drawable的内在大小 -->
android:width="400px"
android:height="400px"
<!-- 虚拟画布的大小 -->
android:viewportWidth="400.0"
android:viewportHeight="400.0">
<path
android:fillColor="#0000FF"
android:strokeColor="#FFFFFF"
android:strokeWidth="4"
android:pathData="M100,100 L300,100 L200,300 z"/>
</vector>
你能用这个基本信息做什么?
从这么多开始,你可以做很多事情。我使用这么多信息创建了一个动画刻度drawable。
最终的checkmark命令是:
M6,11 l3.5,4 l8,-7
这里我的画布大小是24dp x 24dp所以我最初将光标定位在6,11这是检查的起点,我相对于6,11向下移动3.5,4 然后向上相对于新位置8, - 7完成我们的复选标记。由于我最初不希望我的复选标记出现,我将所有lineto命令设置为0,0然后在我的第一个动画中,我将第一行从相对位置0,0设置为相对位置3.5,4。注意,如果我使用绝对位置,这些坐标也不会起作用。
起点:M6,11 l0,0 l0,0
动画步骤1:M6,11 l3.5,4 l0,0
动画步骤2:M6,11 l3.5,4 l8,-7 //完成!
drawable/check_mark.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<group android:name="background">
<path
android:name="circle"
android:fillColor="@color/colorPrimary"
android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0" />
</group>
<group android:name="check">
<path
android:name="tick"
android:pathData="M6,11 l0,0 l0,0"
android:strokeColor="@color/colorAccent"
android:strokeWidth="1" />
</group>
</vector>
drawable-v21/animated_check.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/check_mark">
<target
android:name="tick"
android:animation="@anim/check_animation" />
</animated-vector>
anim/check_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:ordering="sequentially"
android:shareInterpolator="false">
<!-- Step 1 -->
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
android:propertyName="pathData"
android:valueFrom="M6,11 l0,0 l0,0"
android:valueTo="M6,11 l3.5,4 l0,0"
android:valueType="pathType" />
<!-- Step 2 -->
<objectAnimator
android:duration="@android:integer/config_shortAnimTime"
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>
用法
<ImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="100dp"
android:visibility="visible"
app:srcCompat="@drawable/animated_tick" />
mImgCheck = (ImageView) findViewById(R.id.imageView);
((Animatable) mImgCheck.getDrawable()).start();
好极了!你做到了最后!我们应该一起出去玩!