VectorDrawable入门

来源:互联网 发布:织梦pc怎么做手机网站 编辑:程序博客网 时间:2024/05/16 17:06

基础

        api21以后新添加的一个api,用于定义矢量图形。矢量图形可以定义在xml文件中,其根结点为<vector>。但<vector>并不是21以后添加的。

        简单点说:将图形的边界看成一条闭合曲线,通过定义若干个控制点,并将控制点通过直线或者曲线连接起来,再填充上颜色,便形成了一个图形。

vector元素

        有以下几个属性:
        name:定义该矢量图形的名字。
        width,height:定义该矢量图形的固有宽高(必须的)
        viewportHeight,viewportWidth定义画布(viewport)的大小,不需要指定单位。但大小可以理解为一个虚拟单位,将drawable的宽高分成多少等份,在定义path的时候所有数值都是说取drawable宽高的多少份。如viewportWidth和viewportHeight分别为32,32,在path中(16,16)便表示在drawable宽高的中间,(10,10)便表示该点在drawable宽高的10/32,10/32处。所有控制点都必须在viewportWidth和viewportHeight内,超出的部分交不予显示。该属性为必需值
        alpha:图片的不透明度。

path元素

        通过path指定各个控制点的位置。常用属性:
        name:路径的名称。
        fillColor:图形的填充颜色。设置该属性值后,得到的svg图形就会填充满。
        pathData:定义控制点的位置。如下:
<?xml version="1.0" encoding="utf-8"?><vector xmlns:android="http://schemas.android.com/apk/res/android"    android:height="64dp"    android:width="64dp"    android:viewportHeight="100"    android:viewportWidth="100">    <path        android:fillColor="#000000"        android:pathData="M25 0, l 50 50 -50 50Z"/></vector>
其定义了一个三角形,如下:


        在pathData中,有一些字母,这些字母便是指令。
        strokeColor:边界的颜色。
        strokeWidth:边界的宽度。
        strokeAlpha:边界透明度。
        trimPathEnd:从path的结尾处裁剪掉部分path,剪掉的部分不予显示。值从0到1,1表示完全裁剪掉,0表示不裁剪。
        trimPathStart从path的开始处裁剪掉部分path,剪掉的部分不予显示。值从0到1,1表示完全裁剪掉,0表示不裁剪。对trimPath*进行属性动画时,可以实现path路径慢慢显示的效果。

指令

        这些指令是与android中的Path类中的某些方法是对应的。如下:

        M(m):相当于Path.moveTo(),开始新一段的path。

        L(l):相当于Path.lineTo(),移动到指定的点。

        H(h):水平移动。

        V(v):竖直移动。

        C(c):三阶贝塞尔曲线。相当于Path.cubicTo()。

        S(s):同C,但比C要更平滑。

        Q(q):二阶贝塞尔曲线

        T(t):同Q,但比q平滑。

        A(a):弧线。相当于Path.arcTo()。

        Z(z):关闭。相当于Path.close()。

        每一个指令都有大小写,大写表示绝对定位,小写表示相对定位。

        各个指令后需要跟上数量不同的参数,M,L,H,V后面只跟两个,分别表示下一个点的x坐标和y坐标。略。z指令无参数,略。

        c(x1 y1 x2 y2 x y):前两个为贝塞尔曲线的控制点的坐标,最后一个为Path路径上的点的坐标。

        q(x1 y1 x y):第一个表示贝塞尔曲线的控制点坐标,第二个表示path路径上的点的坐标。

        a(rx ry rotation big_flag sweep_flag x y):rx ry分别表示弧线所属椭圆的x,y半轴,rotation表示x轴旋转角度,big-flag表示弧线是否取较大段,1表示是,0表示不是。sweep_flag表示是否顺时针旋转,1表示是,0表示不是。x,y表示终点的坐标。可以这么理解:a之前的点以及x,y确定的点,是椭圆必经的两个点。

        我们知道,对于经历固定两点,且长短半轴固定的椭圆一共会有两个。而big_flag与sweep_flag就是用于确定取哪个椭圆的。如下(项目arc start与arc end代表着固定的两点)


        对于第一排中间位置的图,arc start就是在a之前确定的点,arc end是a中最后两个参数确定的点(有可能是绝对坐标也有可能是相对坐标)。从arc start与end一共有四条线,分别是大小部分与顺逆时针的组合。如:

<vector xmlns:android="http://schemas.android.com/apk/res/android"    android:width="100dp"    android:height="100dp"    android:viewportHeight="100"    android:viewportWidth="100"    >    <path android:name="xxx1"        android:fillColor="#ff0000"        android:pathData="M50 50,a10 10 0 1 1 -10 -10" />    <path android:name="xxx2"        android:fillColor="#4400ff00"        android:pathData="M50 50,L60 40 L40 40z" /></vector>
其效果为

        其中绿色三角形的左边两个顶点分别标识了(40,40)(50,50)两个点,而50,50是xxx1中M50 50所确定的,(40,40)是xxx1中a的最后两个参数确定的(a小写,代表相对位置,所以终点的坐标就是50-10,50-10)。

绝对与相对定位

        指令的大小写分别代表着绝对定位与相对定位。绝对定位指的是这个点在drawable中的坐标,而相对定位指的是这个点相较于前一个点移动的坐标。如:

<vector xmlns:android="http://schemas.android.com/apk/res/android"    android:height="64dp"    android:width="64dp"    android:viewportHeight="100"    android:viewportWidth="100">    <path        android:fillColor="#000000"        android:pathData="M25 0, l50 50 -50 50Z"/>    <path        android:fillColor="#ff0000"        android:pathData="M25 0, L75 50 25 50Z"/></vector>
其效果为:

        从上图可以看出,红三角完全覆盖在黑三角上。首先,两个path的开始点相同,黑三角是相对移动(50,50),从(25,0)移动该值后就为(75,50),所以两个三角形的右边点也完全重合。

group元素

        一组Path集或者group集,并且可以为该group指定一个移动信息,这些信息包括缩放,旋转,平移。也就是说可以为了一个group指定一个动画。常用属性:

        name:group名。

        pivotX,pivotY:旋转绽放的中心点。同path中的坐标一样,都是按viewportWidth,viewportHeight定义的。

        scaleX,scaleY:x,y轴的缩放比例。

        translateX,translateY:x,y轴的平移距离。

        rotation:旋转角度。

animated-vector

        可以执行属性动画的vectordrawable。常用属性

        drawable:用于指定当前要关联的vectordrawable。它可以含有target元素。

target

        用于指定要作用的group和作用的属性动画。常用属性:

        name:指定要作用的group。

        animation:指定该group要执行的属性动画。示例见后面的动画部分。

示例

        该例是一个太极图的效果。如下:

<vector xmlns:android="http://schemas.android.com/apk/res/android"    android:width="1000dp"    android:height="1000dp"    android:viewportHeight="600"    android:viewportWidth="600">    <path        android:fillColor="#ffffff"        android:pathData="M200 200,m0 -100,a100 100 0 1 1 0 200z" />    <path        android:fillColor="#000000"        android:pathData="M200 200,m0 -100,a100 100 0 1 0 0 200z" />    <path        android:fillColor="#ffffff"        android:pathData="M200 150,m0 50,a50 50 0 1 1 0 -100,a50 50 0 1 1 0 100z" />    <path        android:fillColor="#000000"        android:pathData="M200 250,m0 50,a50 50 0 1 0 0 -100z" />    <path        android:fillColor="#000000"        android:pathData="M200 150,m0 10,a10 10 0 1 1 0 -20,a10 10 0 1 1 0 20z" />    <path        android:fillColor="#ffffff"        android:pathData="M200 250,m0 10,a10 10 0 1 0 0 -20,a10 10 0 1 0 0 20z" /></vector>
其效果图为:

动画

        使用属性动画可以使vector动起来。主要分为三步:

        1,创建一个vectordrawable

        2,创建属性动画

        3,创建AnimatedVectorDrawable对象,并与第一步创建的vectordrawable关联,且与第2步创建的属性动画关联。如下:

<vector xmlns:android="http://schemas.android.com/apk/res/android"    android:width="1000dp"    android:height="1000dp"    android:viewportHeight="600"    android:viewportWidth="600">    <group        android:name="taiji"        android:pivotX="200"        android:pivotY="200">        <path            android:fillColor="#ffffff"            android:pathData="M200 200,m0 -100,a100 100 0 1 1 0 200z" />        <path            android:fillColor="#000000"            android:pathData="M200 200,m0 -100,a100 100 0 1 0 0 200z" />        <path            android:fillColor="#ffffff"            android:pathData="M200 150,m0 50,a50 50 0 1 1 0 -100,a50 50 0 1 1 0 100z" />        <path            android:fillColor="#000000"            android:pathData="M200 250,m0 50,a50 50 0 1 0 0 -100z" />        <path            android:fillColor="#000000"            android:pathData="M200 150,m0 10,a10 10 0 1 1 0 -20,a10 10 0 1 1 0 20z" />        <path            android:fillColor="#ffffff"            android:pathData="M200 250,m0 10,a10 10 0 1 0 0 -20,a10 10 0 1 0 0 20z" />    </group></vector>
        这是上面的太极图,只不过将所有的path使用group包裹起来。因为group有动画属性,在使用属性动画时,需要使用这些属性。
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/demo_vector">    <target        android:name="taiji"        android:animation="@animator/taiji_anim" /></animated-vector>
        通过drawable属性关联要操作的vectordrawable。通过target指定vectordrawable中哪一部分指定哪个动画。对应的属性动画如下:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="2000"    android:propertyName="rotation"    android:valueFrom="360"    android:repeatCount="infinite"    android:valueType="floatType"    android:valueTo="0" />

        这里指定的valueType,该属性有三个值,floatType,intType和pathType。

        使用pathType时,可以对vectordrawable中的pathData进行修改,达到一引起很炫的效果。如下:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="2000"    android:propertyName="pathData"    android:valueFrom="M170 250,Q200 275 230 250"    android:repeatCount="infinite"    android:repeatMode="reverse"    android:valueType="pathType"    android:valueTo="M170 250,Q200 225 230 250" />
        使用该属性动画时,可以将pathData的值从valueFrom转成valueTo。从而实现pathData的转变,实现动画。其对应的vector为:
<vector xmlns:android="http://schemas.android.com/apk/res/android"    android:width="1000dp"    android:height="1000dp"    android:viewportHeight="600"    android:viewportWidth="600">    <path        android:fillColor="#ffffff"        android:pathData="M200 200,m0 -100,a100 100 0 1 1 0 200,a100 100 0 1 1 0 -200z" />    <path        android:fillColor="#ff0000"        android:pathData="M160 170,m0 -15,a15 15 0 1 1 0 30,a15 15 0 1 1 0 -30z" />    <path        android:fillColor="#ff0000"        android:pathData="M230 170,m0 -15,a15 15 0 1 1 0 30,a15 15 0 1 1 0 -30z" />    <path        android:name="taiji"        android:pathData="M170 250,Q200 225 230 250"        android:strokeColor="#00ff00"        android:strokeLineCap="round"        android:strokeWidth="8" /></vector>

        使用该drawable时,可以发现图案由笑脸转变为哭脸。

兼容

        AppCompat中已经兼容了VectorDrawable,最低到api 7,但AnimatedVectorDrawableCompat到api 11。然而不管怎么说,4.0以上的都可以用(让4.0以下的见鬼去吧)。

       参考

        0,导入appcompat版本要求23.2.0以上。因为它就是23.2这个版本加入的兼容。

        1,配置build.gradle。gradle 2.0+的方法如下(1.4以下的看参考):
 android {     defaultConfig {       vectorDrawables.useSupportLibrary = true      }   }
        如果不配置这一步,会出现异常信息大概如下:
Caused by: java.io.FileNotFoundException: Corrupt XML binary file

        2,Activity继承AppCompatActivity。如果不兼容第3步会有问题。

        3,在xml文件中,通过srcCompat引用定义的<vector>文件或普通的Png图片。也就是使用srcCompat代替src。而AppCompatActivity对该属性做了处理。如下:

    <ImageView        app:srcCompat="@drawable/ic_alarm_add_black_24dp"        android:id="@+id/fragment_forecast"        android:layout_width="100dp"        android:layout_height="100dp" />    <ImageView        android:tint="#ffffff"        app:srcCompat="@mipmap/ic_launcher"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView" />

        如果第2步不继承于AppCompatActivity的话,这一步引用普通图片的时候会不显示。

        3.1,也可通过java代码调用setImageResource进行设置,如下:

        ImageView iv = (ImageView) findViewById(R.id.fragment_forecast);        VectorDrawableCompat drawableCompat = VectorDrawableCompat.create(getResources(), R.drawable.ic_alarm_add_black_24dp,getTheme());        iv.setImageDrawable(drawableCompat);
        上述只是将矢量图做为一个ImageView的src,当然也可以用作StateListDrawable,或者TextView#drawLeft等。只不过只能通过代码进行设置了。






0 0