Android 开发 VectorDrawable 矢量图+属性动画 使用总结

原文:https://blog.csdn.net/louyulin/article/details/79424105

另外附一个讲解位图转换成矢量图的博客:位图快速转矢量图的5种方法

本人确认 Image Vectorizer  在线转换矢量图简单牛逼好用

然后看一下效果图:

前两个图标是让android的组件使用VectorDrawable

后面的是动画效果 后面会详细介绍.

什么是VectorDrawable

VectorDrawable 是Android特有的SVG矢量图加载机制 这种机制将svg以xml文件解析出来 Path代表着一条线的路径

在AndroidStudio中创建一个VectorDrawable:

点进去之后的icon可以选择系统自带的 也可以选择右侧localfail 需要美工提供svg 或者去阿里矢量图

选择一个会生成一个xml文件 我选择的是朝下的箭头

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"
            android:fillColor="#010101"/>
    </vector>

这个path代表着vectorDrawable是如何在绘制这个路径

上面的width和height是宽高

viewportwidth 是将这个图片宽度虚拟的平分24份  

path是路径的语法 毕竟我们图片都可以直接转换的 所以语法不需要进行深入的理解

如何加载VectorDrawable资源

因为谷歌是从5.0才开始支持VectorDrawable,那么如果是5.0以下的系统需要进行一些简单的配置才可以加载静态VectorDrawable资源

前提: gradle版本在1.2以上

    defaultConfig {
      vectorDrawables.useSupportLibrary = true
        }

然后我们要在加载这个布局的Activity中写一个静态代码块

    static {
 
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

配置完这两条之后我们就可以将ImaveView配置上矢量图资源文件了

 <ImageView
        android:layout_gravity="center_horizontal"
        android:layout_width="35dp"
        android:layout_height="40dp"
        app:srcCompat="@drawable/ic_access_alarm_black_24dp"/>

那么这是静态的组件我们这样配置,如果是一个Button的话 我们这样配置是无效的

给Button配置矢量图资源我们需要通过selector来间接的完成~

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_access_alarm_black_24dp" android:state_pressed="true"/>
        <item android:drawable="@drawable/ic_check_box_outline_blank_black_24dp" android:state_pressed="false"/>
    </selector>

然后把这个selctor设置给button

     <Button
            android:layout_gravity="center_horizontal"
            android:background="@drawable/bg_btn"
            android:layout_width="50dp"
            android:layout_height="50dp" />

好的 关于如何静态加载矢量图总结完了 下面讲解如何与属性动画一起实现效果

VectorDrawable与属性动画结合使用

首先我要强调一个特殊的情况,以我两个箭头左右摇摆的这个为例子(这个箭头是直接从系统素材库中生成)

如果我们直接生成的话 那么他的vector xml是:

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
            android:width="24dp"
            android:height="24dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
        <path
            android:fillColor="#FF000000"
            android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3z
            M14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z"/>
    </vector>

path标签中的pathData 需要格外注意一下,因为我选择的这个矢量图 他是由两个完全分离开的部分组成,在代码中一个M代表一个部分,如果你删掉第二个M之后包裹第二个M的代码 那么右边的箭头在预览区中消失了

如果我们要控制这个VectorDrawable进行动画操作,那么我们需要调用group这个标签 我先展示一下

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <group
        android:name="left">
        <path
            android:fillColor="#f88"
            android:pathData="M9.01,14L2,14v2h7.01v3L13,15l-3.99,-4v3z"/>
    </group>
 
    <group
        android:name="right">
        <path
            android:fillColor="#f88"
            android:pathData="M14.99,13v-3L22,10L22,8h-7.01L14.99,5L11,9l3.99,4z">
        </path>
    </group>
</vector>

把每个M的部分用group标签包裹起来

group的name会对应我们等一下创建的粘合器文件中的属性

粘合器是什么?将VectorDrawable和objectAnimator属性动画进行连接

下面我们要创建两个objectAnimator文件 分别起名 anim_left anim_right 

注意这里创建的文件夹是animator

anim_left:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:interpolator/overshoot"
        android:duration="1000"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:propertyName="translateX"
        android:valueFrom="0"
        android:valueTo="10"
        android:valueType="floatType">
     
    </objectAnimator>

anim_right:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@android:interpolator/overshoot"
        android:duration="1000"
        android:repeatMode="reverse"
        android:repeatCount="infinite"
        android:propertyName="translateX"
        android:valueFrom="0"
        android:valueTo="-10"
        android:valueType="floatType">
     
    </objectAnimator>

我们创建了两个平移的属性动画 属性动画的具体属性我在上一篇文章中有总结

最后我们在drawable文件目录下来创建粘合器文件:

arrow_anim.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/arrow">
        <target
            android:name="left"
            android:animation="@animator/anim_left" />
        <target
            android:name="right"
            android:animation="@animator/anim_right" />
    </animated-vector>

targe是要对应的属性动画文件 这回也对应上我上面写的group标签中的name属性了,这样属性动画和我们的VectorDrawable就一一对应上了

然后我们把这个粘合器设置到imageview上

    <ImageView
        android:id="@+id/anim"
        android:layout_width="146dp"
        android:layout_height="132dp"
        app:srcCompat="@drawable/arrow_anim" />

下面是调用动画的java代码

 Drawable drawable = imageView.getDrawable();
                if (drawable instanceof Animatable) {
                    ((Animatable) drawable).start();
 
                }

下面总结trimPath与属性动画

trimPath与属性动画

下面我要用放大镜的这个例子总结这个点

首先还是先创建VectorDrawable的资源文件 并且根据M分割 (因为动画不同 所以不需要grop分组)

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="150dp"
        android:height="24dp"
        android:viewportHeight="24"
        android:viewportWidth="150">
        
            <path
                android:name="search"
                android:pathData="M141,17 A9,9 0 1,1 142,16 L149,23"
                android:strokeAlpha="0.8"
                android:strokeColor="#000000"
                android:strokeLineCap="round"/>
     
     
     
       
        <path
            android:name="bar"
            android:pathData="M0,23 L149,23"
            android:strokeAlpha="0.8"
            android:strokeColor="#000000"
            android:strokeLineCap="square"
            android:strokeWidth="2"/>
    </vector>

然后我们创建两个objectAnimator文件在animator目录下

anim_search.xml 放大镜动画:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:propertyName="trimPathStart"
        android:valueFrom="1"
        android:valueTo="0"
        android:valueType="floatType">
     
    </objectAnimator>

anim_bar横线动画:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:propertyName="trimPathStart"
        android:valueFrom="1"
        android:valueTo="0"
        android:valueType="floatType">
    </objectAnimator>

其实这两个是一样的 但是他们俩如何实现动画的呢 

 android:propertyName="trimPathStart"

这个属性起到了关键

配合下面两个属性一起就是开始的时候 我的path长度是0 慢慢在3秒内到了1的长度也就是百分之百 不知道体会到了没有

下面还是老套路 粘合器跟第一个例子是一样我就不贴了源码里面都有

然后我们用想通java代码调用及可 下面介绍第三个例子

PathData与属性动画

如果我们想要把五角星硬生生的变成六边形,那么我们就可以修改属性动画文件中的属性就可以达到(后面会强调关于他的兼容性问题)

首先还是老套路 先找一个五角星的VectorDrawablexml文件设置给imageview作为默认图片

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="120dp"
        android:height="120dp"
        android:viewportHeight="64"
        android:viewportWidth="64">
            <path
                android:name="star"
                android:fillColor="#22e171"
                android:pathData="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"
                android:strokeColor="#000000"
                android:strokeWidth="1"/>
    </vector>

我们新建一个anim_fivestar.xml在animator目录下

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"
        android:valueTo="M 48,54 L 31,54 15,54 10,35 6,23 25,10 32,4 40,10 58,23 54,35 z"
        android:valueType="pathType">
    </objectAnimator>

第一个path是五角星的path 第二个path是六边形的path 相信大家都看明白是怎么回事了

然后再配置连接器 

下面就是如何调用这个动画了

首先这个pathData直接改变的动画目前谷歌是不支持5.0以下的手机的 所以使用这总方式实现炫酷动画的小伙伴们一定要慎用啊

判断完手机系统版本后 我们就调用下面的java代码开始动画

       fivestart = (ImageView) findViewById(R.id.fivestart);
            AnimatedVectorDrawable drawable= (AnimatedVectorDrawable) getDrawable(R.drawable.fivestart_anim);
            fivestart.setImageDrawable(drawable);
            if (drawable != null){
                drawable.start();
            }

发生了一点点小变化 也就是我们要直接得到粘合器的drawable对象并强转为AnimatedVectorDrawable类型

然后我们再给iamgeview通话java代码进行设置并开始

但是及时是通过java代码动态设置

相应的组件xml上也别忘了设置这个app属性

 <ImageView
        android:id="@+id/fivestart"
        app:srcCompat="@drawable/fivestart_anim"
        android:layout_width="100dp"
        android:layout_height="100dp" />

猜你喜欢

转载自blog.csdn.net/qq_37217804/article/details/81914271