Android 开发 VectorDrawable 矢量图 (三)矢量图动画
简介——矢量动画2种方式与流程
矢量动画有一些不一样的细节,这里需要提前了解,否则容易在后续使用的时候困惑。
group动画
使用group包裹后的动画,为什么要使用它来包裹path?因为属性动画要改变绘制的图片属性来实现动画,可是path标签中并没有translateX和translateY属性,因此,VectorDrawable要想使用属性,就需要用group标签来封装path标签,将属性动画作用在group标签中,这里使用group标签将vector图片分成了两组,如果图片比较复杂,会将其分成多组。但是group不支持直接操作path的属性。所以这种动画形式是直接移动整个path或者矢量图,它不能根据矢量图参数来变化动画。另外它的添加和启动动画方式与path的name的动画不同。
path动画
直接使用path的name的动画,这个动画支持trimPathStart、trimPathEnd、pathData,fillColor,fillAlpha这几种与path有关的属性,这种动画形式可以直接看懂,trimPathStart与trimPathEnd是绘制步骤动画、pathData是改变参数动画(变形动画)。另外它的添加和启动动画方式与group包裹后的动画不同。
基本流程:
- 创建矢量图
 - 创建animator目录(注意!是animator目录。不是anim目录。)
 - 在animator里添加动画xml
 - 在drawable目录里创建 animated-vector 组合器文件,组合动画xml与矢量图xml
 - 在View 添加这个组合器
 
属性说明
set
一个set中可以有多个objectAnimator,通过ordering属性控制执行顺序。ordering:取值["sequentially"|"together"], sequentially(默认)。
- <set android:ordering="sequentially"> 顺序执行objectAnimator
 - <set android:ordering="together"> 同时执行objectAnimator
 
objectAnimator
objectAnimator中一下这些属性
- propertyName 动画属性名称
 - valueType 值的类型
 - valueFrom 动画的起始值
 - valueTo 动画的结束值
 - repeatCount 重复次数
 - repeatMode 重复模式
 - duration 动画时长
 - interpolator 动画插值
 - startOffset 动画延迟开始时间
 
propertyName属性(属性名)
propertyName:指定动作属性如下:
- translateX X轴移动
 - translateY Y轴移动
 - trimPathStart 路径开始
 - trimPathEnd 路径结束
 - scaleX X轴放大或者缩小比例
 - scaleY Y轴放大或者缩小比例
 - rotation 旋转
 - fillAlpha 透明度
 - fillColor 颜色
 
Vector里面的属性基本上都可以(需要注意target里面绑定的是group就只能使用当前group的属性,下级group或path等不能使用,绑定的path就只能使用当前path的属性,clip-path一样)。
valueType属性(属性值类型)
valueType:PropertyName指定属性值的类型,共有四种类型,分别是:["intType"|"floatType"|"colorType"|pathType]。
valueFrom、valueTo属性(动画初始和结束值)
valueFrom:PropertyName指定属性的初始值,值的类型为ValueType(如位置、颜色、透明、PathData等)。
valueTo:PropertyName指定属性的结束值,值的类型为ValueType。
repeatCount、repeatMode属性(动画重复次数和样式)
repeatCount:定义动画重复次数,["infinite"]为无限次。
repeatMode:定义重复的行为 ["restart"|"reverse"], restart:直接跳到起始位置重新开始;reverse:倒退到起始位置重新开始。
duration属性(动画时间)
duration:动画执行一次的时间,单位ms。
interpolator属性(动画过程控制)
interpolator:控制动画的运行过程。Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等。可以自己定义,也可以使用默认的,列如:
Accelerate:加速,共有下面四种模式
["@android:interpolator/accelerate_decelerate"|"@android:interpolator/accelerate_cubic"|
"@android:interpolator/accelerate_quad"|"@android:interpolator/accelerate_ quint "]
accelerate_decelerate:在动画开始与结束的地方速率改变比较慢,在中间的时候加速;
accelerate_cubic:拟合立方缓和函数的曲线加速。
accelerate_quad:曲线匹配的quadtratic缓解功能加速。
accelerate_ quint:曲线匹配功能昆特缓解加速。
Decelerate:减速,共有四种模式,同Accelerate。
["@android:interpolator/accelerate_decelerate"|"@android:interpolator/decelerate_cubic"|
"@android:interpolator/decelerate_quad"|"@android:interpolator/decelerate_ quint "]。
Anticipate:开始的时候向后然后向前甩["@android:interpolator/accelerate_decelerate"] 。
AnticipateOvershoot:开始的时候向后然后向前甩一定值后返回最后的值["@android:interpolator/anticipate_overshoot"] 。
Bounce:动画结束的时候弹起["@android:interpolator/bounce"] 。         
Cycle:动画循环播放特定的次数,速率改变沿着正弦曲线["@android:interpolator/cycle"] 。
Linear:以常量速率改变["@android:interpolator/linear"] 。              
Overshoot:向前甩一定值后再回到原来位置["@android:interpolator/overshoot"]。
startOffset属性(延时)
延迟播放的时间,单位ms,只延时第一次播放,重复播放时不延时。
实现动画
group 包裹动画:
例子1
效果图:

步骤一 创建矢量图
在drawable目录
my_svg.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportWidth="50.0"
android:viewportHeight="50.0"> <group
android:name="ic_right_path"> <path
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="5"
android:pathData="M20,10 L35,27 M20,40 L35,24"/> </group> </vector>
步骤二 创建动画xml
在animator目录
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="3000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="translateX"
android:valueFrom="0"
android:valueTo="10"
android:valueType="floatType"> </objectAnimator>
虽然上面已经说明过属性了,但是我还是在啰嗦解释一下:
动画插补器:android:interpolator="@android:interpolator/decelerate_cubic"   这里使用的是快到最后动画减速的属性
动画持续时间:android:duration="3000"  这里设置的是3秒
动画重复模式:android:repeatMode="reverse" 这里设置的是倒退到起始位置重新开始动画
动画属性:android:propertyName="translateX" 这里设置的是X轴移动
动画开始值:   android:valueFrom="0"
动画完成值:android:valueTo="10"
参数属性:android:valueType="floatType"  这里设置的是浮点值
步骤三 创建组合器
在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/my_svg"> <target
android:animation="@animator/ic_right_path_animator"
android:name="ic_right_path"/> </animated-vector>
步骤四 在布局xml上的ImageView里添加组合器 arrow_anim.xml
<ImageView
android:id="@+id/ic_anim"
android:layout_width="300dp"
android:layout_height="300dp"
android:src="@drawable/arrow_anim"
android:layout_centerInParent="true" />
步骤五 启动动画
mIcAnim = (ImageView)findViewById(R.id.ic_anim);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Drawable drawable = mIcAnim.getDrawable();
if (drawable instanceof Animatable) {
((Animatable) drawable).start(); }
}
});
直接使用path name的动画:
trimPathStart属性
例子1:
效果图

步骤一 创建矢量图
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportWidth="50.0"
android:viewportHeight="50.0"> <path
android:name="ic_right_path"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="5"
android:pathData="M20,10 L35,27 L20,40"/> </vector>
步骤二 创建动画xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="3000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="trimPathStart"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType"> </objectAnimator>
步骤三 创建组合器
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/my_svg"> <target
android:animation="@animator/ic_right_path_animator"
android:name="ic_right_path"/> </animated-vector>
步骤四 添加组合器和启动动画
这里可以使用2种形式,别问我为什么可以使用两种。我也不知道为什么。。。
第一种就是上面使用group包裹的动画的形式
第二种在代码上添加,注意这里使用的是AnimatedVectorDrawable,这很重要。因为下面的pathData属性必须使用它
mIcAnim = (ImageView)findViewById(R.id.ic_anim);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim);
mIcAnim.setImageDrawable(drawable);
if (drawable != null){
drawable.start();
}
}
});
pathData属性
例子1:
效果图:

步骤一 创建矢量图
在drawable目录
my_svg.xml
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="50dp"
android:height="50dp"
android:viewportWidth="50.0"
android:viewportHeight="50.0"> <path
android:name="ic_right_path"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="5"
android:pathData="M20,10 L35,27 M0,25 L34,25 M20,40 L35,24"/> </vector>
步骤二 在animator目录创建动画xml
ic_right_path_animator.xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="3000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="pathData"
android:valueFrom="M20,10 L35,27 M0,25 L34,25 M20,40 L35,24"
android:valueTo="M0,15 L40,15 M0,25 L40,25 M0,35 L40,35"
android:valueType="pathType"> </objectAnimator>
属性已经在上面有说明了,请对着理解就行了,这里需要注意2点!注意2点!注意2点! 重要事情说三遍!
- 第一点 android:valueType="pathType" 这里使用的参数格式是pathType
 - 第二点 矢量动画要求初始帧的路径命令序列(valueFrom)与结束帧的路径命令序列(valueTo)内的命令必须一一对应,只有参数值可以不同,这样才能插值,从而矢量动画才能执行。否则编译后运行时就崩溃了。
 
步骤三 创建组合器
arrow_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/my_svg"> <target
android:animation="@animator/ic_right_path_animator"
android:name="ic_right_path"/> </animated-vector>
添加动画(这里的动画输入的时候没有联想输入,属于正常请手动敲完)与path名称
步骤四 给ImageView添加arrow_anim 在启动动画
mIcAnim = (ImageView)findViewById(R.id.ic_anim);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AnimatedVectorDrawable drawable =(AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim);
mIcAnim.setImageDrawable(drawable);
if (drawable != null){
drawable.start();
}
}
});
注意!注意!注意!
1.请不要把arrow_anim组合器直接添加到View xml属性里,必须在代码上添加才可以,如果直接添加会报错。
2.这里使用的是AnimatedVectorDrawable类型,添加到View和启动动画,请不要弄错了。
例子2

步骤一 创建矢量图
<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="M15.5,9.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/> <path
android:fillColor="#FF000000"
android:pathData="M8.5,9.5m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/> <path
android:fillColor="#FF000000"
android:pathData="M11.99,2
C6.47,2 2,6.48 2,12
s4.47,10 9.99,10
C17.52,22 22,17.52 22,12S17.52,2 11.99,2z
M12,20
c-4.42,0 -8,-3.58 -8,-8
s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8z"/> <path
android:name="expression"
android:strokeColor="#FF000000"
android:strokeWidth="1.5"
android:pathData="M8,17 C 10,14 14,14 16,17"/> </vector>
说明一下,这里我使用的笑脸是Android studio自带的,一开始的想法是找一个哭脸和笑脸,然后直接找到嘴巴的属性就行了。但是,坑大了,最后发现哭脸和笑脸的嘴巴属性根本不一样。没有办法最后我只能自己直接用三次贝赛曲线画了一个嘴巴。使用各位大神如果想直接使用Android studio的矢量图来做path值变化,请一定检查清楚属性是否一样(只要有一个字母不同就不行!)
步骤二 创建动画xml
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:interpolator/decelerate_cubic"
android:duration="3000"
android:repeatMode="reverse"
android:repeatCount="infinite"
android:propertyName="pathData"
android:valueFrom="M8,17 C 10,14 14,14 16,17"
android:valueTo="M8,15 C 10,18 14,18 16,15"
android:valueType="pathType"> </objectAnimator>
步骤三 创建组合器
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_sentiment_satisfied_black_24dp"> <target
android:animation="@animator/expression"
android:name="expression"/> </animated-vector>
步骤四 向View添加组合器、启动动画
mIcAnim = (ImageView)findViewById(R.id.ic_anim);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim2);
mIcAnim.setImageDrawable(drawable);
if (drawable != null){
drawable.start();
}
}
});
例子3
效果图:

步骤一 创建矢量图
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="100dp"
android:height="100dp"
android:viewportWidth="100.0"
android:viewportHeight="100.0">
<!--头-->
<path
android:fillColor="@color/colorPrimaryDark"
android:pathData="M40,20 C 40,6.5 60,6.5 60,20
M40,20 C 40,33.5 60,33.5 60,20 "/>
<!--躯干-->
<path
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="16"
android:pathData="M48.5,32 L45,60"/>
<!--左手-->
<path
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="10"
android:pathData="M43,35 L25,45 25,55 "/>
<!--右手-->
<path
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="10"
android:pathData="M50,36.3 L75,57"/>
<!--左腿 M43,55 L30,70 L15,65-->
<path
android:name="left_leg"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="10"
android:pathData="M43,55 L30,70 L15,65"/>
<!--右腿 -->
<path
android:name="right_leg"
android:strokeColor="@color/colorPrimaryDark"
android:strokeWidth="10"
android:pathData="M47,55 L55,70 L60,90"/> </vector>
预览效果:
步骤 二 创建对应的动画xml文件
创建左腿动画 step_left.xml
<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:propertyName="pathData"
android:valueFrom="M43,55 L30,70 L15,65"
android:valueTo="M43,55 L45,70 L35,85"
android:valueType="pathType"> </objectAnimator>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:propertyName="pathData"
android:valueFrom="M43,55 L45,70 L35,85"
android:valueTo="M47,55 L55 70 L60 90"
android:valueType="pathType"> </objectAnimator>
</set>
 注意!这里为了让腿部动的不那么尴尬,所以我添加了一个中间值动画。所以这里使用的是组合动画,在set包裹下的objectAnimator 会使用 android:ordering="sequentially"属性按顺序运行动画。注意,我取消了android:repeatMode="reverse"
    android:repeatCount="infinite"  这两个属性,并且使用默认的插补器,所以没有配置插补器。
创建右腿动画 step_right.xml
<?xml version="1.0" encoding="utf-8"?>
<set android:ordering="sequentially"
xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:propertyName="pathData"
android:valueFrom="M43,55 L30,70 L15,65"
android:valueTo="M43,55 L45,70 L35,85"
android:valueType="pathType"> </objectAnimator>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1500"
android:propertyName="pathData"
android:valueFrom="M43,55 L45,70 L35,85"
android:valueTo="M47,55 L55 70 L60 90"
android:valueType="pathType"> </objectAnimator>
</set>
步骤三 创建组合器
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_step"> <target
android:animation="@animator/step_left"
android:name="left_leg"/> <target
android:animation="@animator/step_right"
android:name="right_leg"/> </animated-vector>
步骤四 启动动画
mIcAnim = (ImageView)findViewById(R.id.ic_anim);
mBtnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AnimatedVectorDrawable drawable = (AnimatedVectorDrawable)getDrawable(R.drawable.arrow_anim3);
mIcAnim.setImageDrawable(drawable);
if (drawable != null){
drawable.start();
}
}
});
 												
											Android 开发 VectorDrawable 矢量图 (三)矢量图动画的更多相关文章
- 【Android开发VR实战】三.开发一个寻宝类VR游戏TreasureHunt
		
转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53939303 本文出自[DylanAndroid的博客] [Android开发 ...
 - Android 开发  VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图
		
VectorDrawable 矢量图 三部曲: Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图 Android 开发 VectorDrawabl ...
 - Android 开发 VectorDrawable 矢量图 (二)了解矢量图属性与绘制
		
VectorDrawable 矢量图 三部曲: Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图 Android 开发 VectorDrawabl ...
 - Android开发 - 掌握ConstraintLayout(三)编辑器
		
从本篇博客开始我们开始介绍如何使用ConstraintLayout. 既然ConstraintLayout叫约束布局,首先我们先介绍什么叫约束(Constraints): 约束(Constraints ...
 - Android开发——View滑动的三种实现方式
		
0. 前言 Android开发中,我们常常需要View滑动实现一些绚丽的效果来优化用户体验.一般View的滑动可以用三种方式实现. 转载请注明出处:http://blog.csdn.net/seu ...
 - Android开发笔记(一百三十四)协调布局CoordinatorLayout
		
协调布局CoordinatorLayout Android自5.0之后对UI做了较大的提升.一个重大的改进是推出了MaterialDesign库,而该库的基础即为协调布局CoordinatorLayo ...
 - Android开发进程0.1  轮播图 Scrollview  Fragment
		
轮播图的实现 轮播图通过banner可以较为便捷的实现 1.添加本地依赖,在dependence中搜索相关依赖 2.添加banner的view组件 3.创建适配器GlideImageLoader ex ...
 - [置顶] Android开发实战记录(三)---HelloWorld
		
1.新建Android项目,选择Android Project,然后Next 2.填写项目名称HelloWorld然后next,这里注意下,Java开发的命名规范 3.选择Android SDK版本, ...
 - Android开发艺术探索(三)——View的事件体系
		
一.View基础知识 主要介绍内容有:View的位置参数.MotionEvent和TouchSlope对象.VelocityTracker.GestureDetector和Scroller对象 1.什 ...
 
随机推荐
- GDT临时分段
			
GDT临时分段 GDT临时段说明 现在已经进入了保护模式, 目前的改变 可以访问1M以上的内存了 可以使用32位的指令操作 问题: 由于以前的是实式下段寄存器寻址方式无法使用了,我们必须切换到使用GD ...
 - 【转载】Spring Cloud全家桶主要组件及简要介绍
			
https://blog.csdn.net/xlgen157387/article/details/77773908
 - 禁止WORDPRESS站内搜索的方法
			
如果我们希望禁止站内搜索,毕竟会是的MYSQL负担加重,我们可以禁止掉,然后在使用第三方搜索组件.比如用百度站内搜索或者360站内搜索. function fb_filter_query( $quer ...
 - SpringMvc开发报找不到springmvc配置文件
			
param-name标签属性值必须为contextConfigLocation
 - WebView性能、体验分析与优化
			
育新 徐宏 嘉洁 ·2017-06-09 20:03 在App开发中,内嵌WebView始终占有着一席之地.它能以较低的成本实现Android.iOS和Web的复用,也可以冠冕堂皇的突破苹果对热更新的 ...
 - Mysql 复制一个新表
			
1.复制表结构及数据到新表CREATE TABLE 新表 SELECT * FROM 旧表这种方法会将oldtable中所有的内容都拷贝过来,当然我们可以用delete from newtable;来 ...
 - python中类的创建和实例化
			
python中同样使用关键字class创建一个类,类名称第一个字母大写,可以带括号也可以不带括号: python中实例化类不需要使用关键字new(也没有这个关键字),类的实例化类似函数调用方式: # ...
 - jQuery-1.样式篇
			
jQuery对象与DOM对象 对于才开始接触jQuery库的初学者,我们需要清楚认识一点: jQuery对象与DOM对象是不一样的 可能一时半会分不清楚哪些是jQuery对象,哪些是DOM对象,下面重 ...
 - SSM 与三层架构的关系的简单理解
			
NOTE 1:Spring MVC 编写在表示层,代替了servlet.主要作用就是接收用户的请求,完成响应或转发; NOTE 2:Mybatis 编写在dao层,代替了原来的JDBC,就要就是用来跟 ...
 - 购物车存到cookie
			
为什么不存session? 首先,session存在时间限制,会定期清空的,而cookie如果不主动清或者设置定期则不会清楚: session存放在服务器端,cookie存放在客户端浏览器. 购物车存 ...