Android动画进阶VectorDrawable

动画进阶

VectorDrawable

VectorDrawable是为了让Android支持SVG而诞生的。

  1. 从大小上来看 : VectorDrawable < SVG < PNG ,(压缩应用大小的一个选择方向,虽然现在也有WebP)
  2. 加载解析速度上:VectorDrawable 只支持SVG的Path标签,最大的原因就是为了解决SVG解析较慢的问题, 而且Path也是可以绘制所有图形的
  3. 导入SVG生成VectorDrawable : File -> New -> Vector Asset
  4. VectorDrawable结构如下
<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="M17,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
</vector>
  1. Gradle的默认配置添加vectorDrawables.useSupportLibrary = true

静态使用

  • 无状态的控件使用:如ImageView

    • app:srcCompat="@drawable/vector_test"
  • 有状态的控件使用: 如Button

    • 通过设置background为Selector,在Selector中使用Vector
    • 注意!!!要在该页面的Activity或Fragment中设置兼容支持
    static {
    //设置VectorDrawable兼容支持,否则会闪退
       AppCompatDelegate
           .setCompatVectorFromResourcesEnabled(true);
    }
    

动态使用(动画)

VectorDrawable最重点的使用
最后效果预览:

device-2017-03-31-171032.mp4_1490953187.gif

VectorDrawable资源

Vector资源.png
  • group 的 name :路径的标志,做平移,缩放,透明度,旋转这些path不具备的属性动画时要使用
  • path 的 name :路径的标志,做Vector特有的属性动画时要使用,如fillColorstrokeColorpathData, trimPathStart , trimPathEnd
  • viewportHeight : 相当于高度总权重的值,下面的绘制的高度数值也是基于这个值为总量
  • viewportWidth : 相当于宽度总权重的值,下面的绘制的宽度数值也是基于这个值为总量
  • pathData : 具体绘制图像的路径数据
  • fillColor : 填充颜色
  • strokeColor : 边框颜色
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="100dp"
        android:height="100dp"
        android:viewportHeight="1024.0"
        android:viewportWidth="1025.0">

    <group android:name="hollow">
        <path
            android:name="hollow_path"
            android:fillColor="@android:color/darker_gray"
            android:pathData="M920.7,870.4C920.7,898.7 897.6,921.6 869.1,921.6L765.8,921.6C737.3,921.6 714.1,898.7 714.1,870.4L714.1,153.6C714.1,125.3 737.3,102.4 765.8,102.4L869.1,102.4C897.6,102.4 920.7,125.3 920.7,153.6L920.7,870.4Z
        M920.7,0 L714.1,0C657.1,0 610.8,45.8 610.8,102.4L610.8,921.6C610.8,978.2 657.1,1024 714.1,1024L920.7,1024C977.8,1024 1024,978.2 1024,921.6L1024,102.4C1024,45.8 977.8,0 920.7,0L920.7,0Z"/>
    </group>

    <group android:name="arrow">
        <path
            android:name="arrow_path"
            android:fillColor="@android:color/darker_gray"
            android:pathData="M49.9,563.2 L306.4,563.2C328.6,563.2 339.8,582.1 324,597.5L240,675.9C220.5,695 220.5,724.1 240,743.1 259.5,762.2 291.1,761.2 310.6,742.2L487.2,569C526.2,530.9 526.2,468.9 487.2,430.8 459.6,403.6 338.4,285 310.6,257.9 291.1,238.8 259.5,238.8 240,257.9 220.5,277 220.5,307.9 240,327L324,414.1C339.7,429.5 328.5,460.8 306.3,460.8L49.9,460.8C22.4,460.8 0,485 0,512 0,539 22.4,563.2 49.9,563.2L49.9,563.2Z"/>
    </group>

</vector>

ObjectAnimator资源

动画的具体操作

  • 路径绘制动画:从开始到结束的路径的动画
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:propertyName="trimPathStart"
    android:valueFrom="0"
    android:valueTo="1"
    android:valueType="floatType"
    >

</objectAnimator>
  • 路径转换动画: 从一个图形变成另外一个图形
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:androd="http://schemas.android.com/apk/res/android"
    androd:duration="3000"
    androd:propertyName="pathData"
    androd:valueFrom="M 48,54 L 31,42 15,54 21,35 6,23 25,23 32,4 40,23 58,23 42,35 z"
    androd:valueTo="M 48,54 L 31,54 15,54 10,35 6,23 25,10 32,4 40,10 58,23 54,35 z"
    androd:valueType="pathType">

</objectAnimator>
  • 颜色转换动画: 实现颜色的渐变(边框颜色就是fillColor变成strokeColor)
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:propertyName="fillColor"
    android:valueFrom="@android:color/darker_gray"
    android:valueTo="@android:color/holo_red_light"
    android:valueType="colorType">
</objectAnimator>
  • 上平移动画: !!值得一提的是,平移的距离是和VectorDrawable的viewportHeightviewWidth 挂钩的, 好比Vector的viewportHeight=100,那么我上一50,就等于移动了图形总面积的50%
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:interpolator="@android:interpolator/overshoot"
    android:propertyName="translateY"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:valueFrom="0"
    android:valueTo="-300"
    android:valueType="floatType"
    >
</objectAnimator>
  • 剩下的缩放,旋转,透明度和普通的属性动画差不多就不贴出了

Animated-vector资源

VectorDrawable 和 ObjectAnimator的 粘合剂
将动画资源作用到Vector资源的核心

  • 预览中箭头左移,正方形上移的动画:
<?xml version="1.0" encoding="utf-8"?>
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_svg_arrow_right_bank"
    >

    <target
        android:name="hollow"
        android:animation="@animator/anim_translate_top_iii"/>
    <target
        android:name="arrow"
        android:animation="@animator/anim_translate_right_i"/>
    <target
        android:name="arrow_path"
        android:animation="@animator/anim_color_turn_red_fill"/>

</animated-vector>
  • 预览中的红色螺旋绘制动画:
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
                 xmlns:tools="http://schemas.android.com/tools"
                 android:drawable="@drawable/ic_svg_icon_helix"
                 tools:targetApi="lollipop">
    <target
        android:name="helix"
        android:animation="@animator/anim_path_end"/>
    <target
        android:name="helix"
        android:animation="@animator/anim_color_turn_red"/>

</animated-vector>

代码启动

  1. 首先在布局资源中使用
<ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="doClick"
            app:srcCompat="@drawable/anim_arrow_bank_play"/>

        <TextView
            android:id="@+id/tv_set"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="9dp"
            android:drawableTop="@drawable/anim_three_point_loading"
            android:onClick="doClick"
            android:scaleType="fitXY"
            android:text="三点动画组合"
            />

        <TextView
            android:id="@+id/tv_helix"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="9dp"
            android:drawableTop="@drawable/anim_helix_play"
            android:gravity="center"
            android:onClick="doClick"
            android:scaleType="fitXY"
            android:text="超级螺旋"
            />
  1. 代码中启动动画:
 public void doClick(View view) {

        /**
         * 这个主要针对pathData路径变化
         * 只支持5.0以上的版本
         */
        if (view.getId() == R.id.tv_path) {
            AnimatedVectorDrawable vectorDrawable = (AnimatedVectorDrawable) getDrawable(R.drawable.anim_square_play);
            ((TextView) view).setCompoundDrawables(null, vectorDrawable, null, null);
            vectorDrawable.start();
        } else {

            /**
             * TextView中获取资源并启动
             */
            if (view instanceof TextView) {
                Drawable[] drawables = ((TextView) view).getCompoundDrawables();
                ((Animatable) drawables[1]).start();
            }

            /**
             * ImageView中获取资源并启动
             */
            if (view instanceof ImageView) {
                ((Animatable) ((ImageView) view).getDrawable()).start();
            }
        }
    }

一些理解

优势:

  1. 理解了SVG中的知识,可以根据路径很好的拆分,就像上面的箭头和正方形就是一个svg图形,然后拆分进行动画
  2. 路径绘制的优势,UI提供我们需要的SVG路径,我们就可以非常简单的实现路径动画
  3. 除了路径转换(注意不是路径绘制) 以外,其他都是支持向下兼容到3.0

劣势:

  1. 资源文件过多,根据具体图像的动画资源,动画粘合剂资源会出现十分多,需要规范好UI制作的svg,抽取出完善的ObjectAnimator来相互组合使用
  2. 一开始使用会感觉有点繁琐吧,其实我感觉还好,主要看个人吧,如果在自定义View绘制比较弱的话,VectorDrawable提供了很好的解决方案

代码项目Github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容