篇幅比较长,耐心点看,总结了Android中有关动画的细节,包括一些使用的小例子。
源码地址:
https://github.com/StarsAaron/AnimationTestDemo/tree/master
动画
1. View Animation 视图动画
1.1 Frame Animation 帧动画
使用方法:
使用时需要在res下的drawable文件夹中放入需要动画显示的图片,同时在该文件夹中新建一个xml文件。
anim_list.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false" >
<item android:drawable="@drawable/frame1"
android:duration="500"/>
<item android:drawable="@drawable/frame2"
android:duration="500"/>
<item android:drawable="@drawable/frame3"
android:duration="500"/>
<item android:drawable="@drawable/frame4"
android:duration="500"/>
<item android:drawable="@drawable/frame5"
android:duration="500"/>
</animation-list>
给控件设置动画:
image.setBackgroundResource(R.drawable.anim_list);
开启动画:
AnimationDrawable animation_drawable = (AnimationDrawable)image.getBackground();
animation_drawable.start();
停止动画:
animation_drawable.stop();
1.2 Tween Animation 补间动画
知识点:
1) 四种类型动画:alpha
、scale
、translate
、rotate
的xml文件和代码定义方式。
2) Interpolator 插补器使用
3) set 动画组合
注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式
Android 使用 Animation 代表抽象的动画类,它包括如下几个子类:
AlphaAnimation
:透明度改变的动画。需指定动画起、止的透明度(0~1)及持续时间。ScaleAnimation
:大小缩放的动画。需指定动画起、止的缩放比(X、Y 轴向缩放参数)及持续时间。还应通过 pivotX、pivotY 指定缩放中心的坐标。TranslateAnimation
:位移变化的动画。需指定动画起、止的位置(X、Y 坐标)及持续时间。RotateAnimation
:旋转动画。需指定动画起、止的旋转角度(X、Y 轴向缩放参数)及持续时间。还应通过 pivotX、pivotY 指定旋转轴心的坐标。
一旦在程序中通过 AnimationUtils 得到代表补间动画的 Animation 之后,即可调用 View 的如下方法开始对该 View 执行动画。
startAnimation(Animation anim);
Animation类是所有动画(scale、alpha、translate、rotate)的基类。
它所具有的标签及对应函数为:
xml属性 | 代码方法 | 描述 |
---|---|---|
android:duration | setDuration(long) | 动画持续时间,以毫秒为单位 |
android:fillAfter | setFillAfter(boolean) | 如果设置为true,控件动画结束时,将保持动画最后时的状态 |
android:fillBefore | setFillBefore(boolean) | 如果设置为true,控件动画结束时,还原到开始动画前的状态 |
android:fillEnabled | setFillEnabled(boolean) | 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态 |
android:repeatCount | setRepeatCount(int) | 重复次数 |
android:repeatMode | setRepeatMode(int) | 重复类型,有reverse和restart两个值,取值为RESTART或 REVERSE,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。 |
android:interpolator | setInterpolator(Interpolator) | 设定插值器,其实就是指定的动作效果,比如弹跳效果等 |
1.2.1 四种变化
1) alpha透明度
xml中定义
alpha标签——调节透明度
1. 自身属性
- android:fromAlpha 动画开始的透明度,从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明
- android:toAlpha 动画结束时的透明度,也是从0.0 –1.0 ,0.0表示全透明,1.0表示完全不透明
2. 从Animation类继承的属性
注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式
例子:tween_alphaanim.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillBefore="true"
android:fromAlpha="1.0"
android:toAlpha="0.1">
</alpha>
<!-- 透明度控制动画效果 alpha
浮点型值:
fromAlpha 属性为动画起始时透明度
toAlpha 属性为动画结束时透明度
说明:
0.0表示完全透明
1.0表示完全不透明
以上值取0.0-1.0之间的float数据类型的数字
长整型值:
duration 属性为动画持续时间
说明:
时间以毫秒为单位
-->
控件使用动画:
// 透明度
Animation alpaAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_alphaanim);
view.startAnimation(alpaAnimation);
代码中定义AlphaAnimation
对应的构造函数为:
AlphaAnimation(Context context, AttributeSet attrs) 同样,从本地XML加载动画,基本不用
AlphaAnimation(float fromAlpha, float toAlpha)
例子:
// 定义透明度动画
AlphaAnimation alphaAnim = new AlphaAnimation(1.0f, 0.1f);
alphaAnim.setDuration(3000);
alphaAnim.setFillBefore(true);
// 使用动画
view.startAnimation(alphaAnim);
2) scale 缩放
scale标签——调节尺寸
1. 自有属性
- android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
- android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
- android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
- android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
- android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
2. 从Animation类继承的属性
Animation类是所有动画(scale、alpha、translate、rotate)的基类,这里以scale标签为例,讲解一下,Animation类所具有的属性及意义。关于Animation类的官方文档位置为:《Animation》
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
xml中定义
scale标签——调节尺寸
1、自有属性
scale标签是缩放动画,可以实现动态调控件尺寸的效果,有下面几个属性:
android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
2、从Animation类继承的属性
注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式
例子:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="700"
android:fillBefore="true"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="1"
android:repeatMode="restart"
android:toXScale="1.4"
android:toYScale="1.4"
/>
<!--
Animation变化坐标点的参照类型
上面看到,RotateAnimation、ScaleAnimation、TranslateAnimation都存在一对pivotXType,pivotYType参数,
它们是用来指定点的参照类型,使用int类型以静态常量的形式定义在Animation中,它有如下个值:
ABSOLUTE:以绝对坐标为参照。
RELATIVE_TO_PARENT:以父容器为参照。
RELATIVE_TO_SELF:以当前容器为参照。
细心的朋友有发现到,在使用XML定义动画资源的时候,没有关于pivotXType、pivotYType两个属性,其实它们结合到了设定点的坐标中中,
以 pivotXValue、pivotYValue两个属性替代,其中如果需要设定为父容器为参照,需要在属性值后面加"p"即可。
-->
<!-- 尺寸伸缩动画效果 scale
属性:interpolator 指定一个动画的插入器
在我试验过程中,使用android.res.anim中的资源时候发现
有三种动画插入器:
accelerate_decelerate_interpolator 加速-减速 动画插入器
accelerate_interpolator 加速-动画插入器
decelerate_interpolator 减速- 动画插入器
其他的属于特定的动画效果
浮点型值:
fromXScale 属性为动画起始时 X坐标上的伸缩尺寸
toXScale 属性为动画结束时 X坐标上的伸缩尺寸
fromYScale 属性为动画起始时Y坐标上的伸缩尺寸
toYScale 属性为动画结束时Y坐标上的伸缩尺寸
说明:
以上四种属性值
0.0表示收缩到没有
1.0表示正常无伸缩
值小于1.0表示收缩
值大于1.0表示放大
pivotX 属性为动画相对于物件的X坐标的开始位置(坐标原点X点坐标)
pivotY 属性为动画相对于物件的Y坐标的开始位置(坐标原点Y点坐标)
说明:
以上两个属性值 从0%-100%中取值
50%为物件的X或Y方向坐标上的中点位置
长整型值:
duration 属性为动画持续时间
说明: 时间以毫秒为单位
布尔型值:
fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用
-->
tween_alphaanim.xml
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillBefore="true"
android:fromAlpha="1.0"
android:toAlpha="0.1">
</alpha>
<!-- 透明度控制动画效果 alpha
浮点型值:
fromAlpha 属性为动画起始时透明度
toAlpha 属性为动画结束时透明度
说明:
0.0表示完全透明
1.0表示完全不透明
以上值取0.0-1.0之间的float数据类型的数字
长整型值:
duration 属性为动画持续时间
说明:
时间以毫秒为单位
-->
控件使用动画:
// 缩放
Animation scaleAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_scaleanim);
view.startAnimation(scaleAnimation);
代码中定义ScaleAnimation
ScaleAnimation有下面几个构造函数:
- ScaleAnimation(Context context, AttributeSet attrs) 从XML文件加载动画,基本用不到
- ScaleAnimation(float fromX, float toX, float fromY, float toY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
- ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
第一个构造函数是从本地XML文件加载动画,基本用不到的,我们主要看下面三个构造函数。
在标签属性android:pivotX中有三种取值,数,百分数,百分数p;体现在构造函数中,就是最后一个构造函数的pivotXType,它的取值有三个:
- Animation.ABSOLUTE
- Animation.RELATIVE_TO_SELF
- Animation.RELATIVE_TO_PARENT
例子:
// 伸缩动画
Animation scaleAnim = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnim.setDuration(700);
// 使用动画
view.startAnimation(scaleAnim);
3) rotate旋转
rotate标签——旋转
1. 自身属性
- android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p
2. 从Animation类继承的属性
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
xml中定义
rotate标签——旋转
1. 自身属性
- android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
- android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:pivotY 缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p
2. 从Animation类继承的属性
注意:动作定义文件应该存放在res/anim文件夹下,访问时采用R.anim.XXX.xml的方式
例子:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="650">
</rotate>
<!-- rotate 旋转动画效果
属性:interpolator 指定一个动画的插入器
在我试验过程中,使用android.res.anim中的资源时候发现
有三种动画插入器:
accelerate_decelerate_interpolator 加速-减速 动画插入器
accelerate_interpolator 加速-动画插入器
decelerate_interpolator 减速- 动画插入器
其他的属于特定的动画效果
浮点数型值:
fromDegrees 属性为动画起始时物件的角度
toDegrees 属性为动画结束时物件旋转的角度 可以大于360度
说明:
当角度为负数——表示逆时针旋转
当角度为正数——表示顺时针旋转
(负数from——to正数:顺时针旋转)
(负数from——to负数:逆时针旋转)
(正数from——to正数:顺时针旋转)
(正数from——to负数:逆时针旋转)
pivotX 属性为动画相对于物件的X坐标的开始位置
pivotY 属性为动画相对于物件的Y坐标的开始位置
说明: 以上两个属性值 从0%-100%中取值
50%为物件的X或Y方向坐标上的中点位置
长整型值:
duration 属性为动画持续时间
说明: 时间以毫秒为单位
-->
控件使用动画:
// 旋转
Animation rotateAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_rotateanim);
view.startAnimation(rotateAnimation);
代码中定义RotateAnimation
对应的构造函数有:
- RotateAnimation(Context context, AttributeSet attrs) 从本地XML文档加载动画,同样,基本不用
RotateAnimation(float fromDegrees, float toDegrees) - RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
- RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
RotateAnimation跟ScaleAnimation差不多,关键问题同样是pivotXType和pivotYType的选择,同样有三个取值:Animation.ABSOLUTE、Animation.RELATIVE_TO_SELF和Animation.RELATIVE_TO_PARENT;
例子:
// 旋转动画
Animation rotateAnim = new RotateAnimation(0, -650, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnim.setDuration(3000);
rotateAnim.setFillAfter(true);
// 使用动画
view.startAnimation(rotateAnim);
4) translate平移
translate标签 —— 平移
1. 自身属性
- android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
- android:toXDelta 结束点X轴坐标
- android:toYDelta 结束点Y轴坐标
2. 从Animation类继承的属性
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
xml中定义
translate标签 —— 平移
1. 自身属性
- android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
- android:fromYDelta 起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
- android:toXDelta 结束点X轴坐标
- android:toYDelta 结束点Y轴坐标
2. 从Animation类继承的属性
- android:duration 动画持续时间,以毫秒为单位
- android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
- android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
- android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
- android:repeatCount 重复次数
- android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
- android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
例子:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillBefore="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-80"
android:toYDelta="-80">
</translate>
<!-- translate 位置转移动画效果
整型值:
fromXDelta 属性为动画起始时 X坐标上的位置
toXDelta 属性为动画结束时 X坐标上的位置
fromYDelta 属性为动画起始时 Y坐标上的位置
toYDelta 属性为动画结束时 Y坐标上的位置
注意:
没有指定fromXType toXType fromYType toYType 时候,
默认是以自己为相对参照物
长整型值:
duration 属性为动画持续时间
说明: 时间以毫秒为单位
-->
<!-- AnimationSet: http://developer.android.com/reference/android/view/animation/AnimationSet.html-->
控件使用动画:
// 平移
Animation translateAnimation= AnimationUtils.loadAnimation(this, R.anim.tween_translateanim);
view.startAnimation(translateAnimation);
代码中定义TranslateAnimation
对应的构造函数为:
- TranslateAnimation(Context context, AttributeSet attrs) 同样,基本不用
- TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
- TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
由于fromXDelta、fromYDelta、toXDelta、toYDelta这三个属性都具有三种状态,所以在构造函数中,最理想的状态就是第三个构造函数,能够指定每个值的类型,第二个构造函数:TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)使用是绝对数值。只有最后一个构造函数可以指定百分数和相对父控件的百分数。
例子:
// 平移动画
Animation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80,
Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80);
translateAnim.setDuration(2000);
translateAnim.setFillBefore(true);
// 使用动画
view.startAnimation(translateAnim);
AnimatiorSet组合
xml中定义
set标签——定义动作合集
Set标签就可以将几个不同的动作定义成一个组;set标签自已是没有属性的,他的属性都是从Animation继承而来,但当它们用于Set标签时,就会对Set标签下的所有子控件都产生作用。
属性有:(从Animation类继承的属性)
例子:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:fillAfter="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
<scale
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.4"
android:toYScale="1.4"/>
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="720"/>
</set>
<!-- 透明度控制动画效果 alpha
浮点型值:
fromAlpha 属性为动画起始时透明度
toAlpha 属性为动画结束时透明度
说明:
0.0表示完全透明
1.0表示完全不透明
以上值取0.0-1.0之间的float数据类型的数字
长整型值:
duration 属性为动画持续时间
说明:
时间以毫秒为单位
-->
控件使用动画:
// 动画集
Animation setAnimation = AnimationUtils.loadAnimation(this, R.anim.tween_setanim);
view.startAnimation(setAnimation);
代码中定义
- AnimationSet(Context context, AttributeSet attrs) 同样,基本不用
- AnimationSet(boolean shareInterpolator) shareInterpolator取值true或false,取true时,指在AnimationSet中定义一个插值器(interpolater),它下面的所有动画共同。如果设为false,则表示它下面的动画自己定义各自的插值器。
例子:
// 组合动画
AnimationSet setAnim = new AnimationSet(true);
setAnim.addAnimation(alphaAnim);
setAnim.addAnimation(scaleAnim);
setAnim.addAnimation(rotateAnim);
setAnim.setFillAfter(true);
// 使用动画
view.startAnimation(setAnim);
Interpolator插值器
Interpolator
属性是Animation类的一个XML属性,所以alpha、scale、rotate、translate、set都会继承得到这个属性。
InterPolator 根据特定算法计算出整个动画所需动态插入帧的密度和位置。
它是一个接口,定义了所有 Interpolator 都需要实现的方法:
float getInterpolation(float input)
开发者可通过实现 Interpolator 来控制动画的变化速度。
插值器类:
类名 | 描述 |
---|---|
AccelerateDecelerateInterpolator | 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速 |
AccelerateInterpolator | 在动画开始的地方速率改变比较慢,然后开始加速 |
AnticipateInterpolator | 开始的时候向后然后向前甩 |
AnticipateOvershootInterpolator | 开始的时候向后然后向前甩一定值后返回最后的值 |
BounceInterpolator | 动画结束的时候弹起 |
CycleInterpolator | 动画循环播放特定的次数,速率改变沿着正弦曲线 |
DecelerateInterpolator | 在动画开始的地方快然后慢 |
LinearInterpolator | 以常量速率改变 |
OvershootInterpolator | 向前甩一定值后再回到原来位置 |
xml中定义
为了在动画资源文件中指定补间动画所使用的 Interpolator,定义动画的元素 <set.../>
、<alpha.../>
、<scale.../>
、<translate.../>
、<rotate.../>
都可指定一个 android:interpolator 属性以指定动画的变化速度。Android 系统的 R.anim 类中包含了大致常量,它们定义了不同的动画速度。如:
- @android:linear_interpolator :匀速变换
- @android:accelerate_interpolator :加速变换
@android:decelerate_interpolator :减速变换
注:上述常量的写法规律,其实是把系统提供的 Interpolator 实现类的类名的驼峰写法改为下划线写法即可。
例子:
scale标签
先看下XML代码:(从控件中心点,从0放大到1.4倍,保持结束时的状态)
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.4"
android:fromYScale="0.0"
android:toYScale="1.4"
android:pivotX="50%"
android:pivotY="50%"
android:duration="700"
android:fillAfter="true"
/>
rotate标签
先看下XML代码:(从控件中心点,从0放大到1.4倍,保持结束时的状态)
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%
android:duration="700"
android:fillAfter="true"
/>
alpha标签
将透明度从0变成1.0,使用不同的插值器看看有什么不同(因为只是透明度的变化,所以基本看不出来有什么不同)
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="3000"
android:fillAfter="true"
/>
translate标签
把控件从(0,0)平移到(-200,-200)的位置,保持结束时状态不变,使用不同插值器。
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXDelta="0"
android:toXDelta="-200"
android:fromYDelta="0"
android:toYDelta="-200"
android:duration="2000"
android:fillAfter="true"
/>
代码中定义
Android 为 Interpolator 提供了如下几个实现类:
- LinearInterpolator :动画以匀速改变。
- AccelerateInterpolator :动画以匀加速改变。
- AccelerateDecelerateInterpolator :动画的改变以匀加速开始,以匀减速结束,中间改变最快。
- CycleInterpolator :动画循环播放特定的次数,变化速度按正统曲线改变。
- DecelerateInterpolator :动画以匀减速改变。
例子:
// 插播器动画
Animation interpolateScaleAnim = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
interpolateScaleAnim.setInterpolator(new BounceInterpolator());
interpolateScaleAnim.setDuration(3000);
// 使用动画
view.startAnimation(interpolateScaleAnim );
动画监听
AnimationSet as=new AnimationSet(true);
RotateAnimation al=new RotateAnimation(0,-720,Animation.RELATIVE_TO_PARENT
,0.5f,Animation.RELATIVE_TO_PARENT,0.5f);
al.setDuration(3000);
al.setAnimationListener(new AnimationListener() {
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
}
public void onAnimationRepeat(Animation animation) {
}
});
as.addAnimation(al);
iv.startAnimation(as);
2. Property Animation属性动画
从某种角度看,属性动画是增强版的补间动画,其强大体现在两方面:
- 补间动画只能定义两个关键帧在透明度、旋转、倾斜、位移这4个方面的变化,而属性动画可以定义任何属性的变化。
- 补间动画只能对 UI 组件执行动画,而属性动画几乎可以对任何对象执行动画。
属性动画也需要定义如下几方面属性:
- android:duration :动画持续时间。默认值 300 毫秒。
- android:interpolator :动画插值方式。与补间动画中插值属性作用类似。
- android:repeatCount :动画重复次数。
- android:repeatMode :重复方式。指定动画结束后,从头重播还是反向播放。
2.1 两种属性动画
1) ValueAnimator
可按如下4个步骤:
- 调用 ValueAnimator 的 ofInt()、ofFloat() 或 ofObject() 静态方法创建 ValueAnimator 实例。
- 调用 ValueAnimator 的 setXxx() 设置动画持续时间、插值方式、重复次数等。
- 调用 ValueAnimator 的 start() 方法启动动画。
为 ValueAnimator 注册 AnimatorUpdateListener 监听器,用以监听 ValueAnimator 计算出来的值的改变(可通过 getAnimatedValue() 方法获取当前帧的值),并将这些值应用到指定对象。
例子:
ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight());
animator.setTarget(mBlueBall);
animator.setDuration(1000).start();
// animator.setInterpolator(value)
animator.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
view.setTranslationY((Float) animation.getAnimatedValue());
}
});
2) ObjectAnimator
ObjectAnimator 可直接将 ValueAnimator 在动画过程中计算出来的值应用到指定对象的指定属性上,不需要注册监听器。
使用 ObjectAnimator 的 ofInt()、ofFloat() 或 ofObject() 静态方法创建 ValueAnimator 实例时需要指定具体的对象及其属性名。
使用 ObjectAnimator 需注意:
- 须为该对象对应的属性提供 setter 方法,例如 setAlpha(float value) 方法。
- 调用 ObjectAnimator 的 ofInt()、ofFloat() 或 ofObject() 工厂方法时 values… 参数只提供了一个结束值。因而该对象应为该属性提供一个 getter 方法以返回一个开始值。
如果动画的对象是 View,为了能显示动画效果,可能还需在 onAnimationUpdate() 事件监听方法中调用 View.invalidate() 方法来刷新屏幕的显示。(比如对 Drawable 对象的 color 属性执行动画)。
不过 View 定义的 setter 方法(如 setAlpha()、setTranslationX() )都会自动调用 invalidate() 方法了。
代码定义例子:
ObjectAnimator anim = ObjectAnimator
.ofFloat(view, "zhy", 1.0F, 0.2F)
.setDuration(500);
anim.start();
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float cVal = (Float) animation.getAnimatedValue();
view.setAlpha(cVal);
view.setScaleX(cVal);
view.setScaleY(cVal);
}
});
XML定义例子:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="2.0"
android:valueType="floatType" >
</objectAnimator>
调用:
// 加载动画
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);
anim.setTarget(view);
anim.start();
2.2 AnimatorSet组合动画
使用set标签,有一个orderring属性
值:
- together 同时播放
- sequentially 表示一个接一个执行
Xml例子:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together" >
<objectAnimator
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1"
android:valueTo="0.5" >
</objectAnimator>
<objectAnimator
android:duration="1000"
android:propertyName="scaleY"
android:valueFrom="1"
android:valueTo="0.5" >
</objectAnimator>
</set>
// 加载动画
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);
mMv.setPivotX(0);
mMv.setPivotY(0);
//显式的调用invalidate
mMv.invalidate();
anim.setTarget(mMv);
anim.start();
代码例子:
public void togetherRun(View view) {
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",1.0f, 2f);
AnimatorSet animSet = new AnimatorSet();
animSet.setDuration(2000);
animSet.setInterpolator(new LinearInterpolator());
//两个动画同时执行
animSet.playTogether(anim1, anim2);
//animSet.playSequentially(items)
animSet.start();
}
public void playWithAfter(View view) {
float cx = mBlueBall.getX();
ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",1.0f, 2f);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",1.0f, 2f);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,"x", cx, 0f);
ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,"x", cx);
/**
* anim1,anim2,anim3同时执行
* anim4接着执行
*/
AnimatorSet animSet = new AnimatorSet();
animSet.play(anim1).with(anim2);
animSet.play(anim2).with(anim3);
animSet.play(anim4).after(anim3);
animSet.setDuration(1000);
animSet.start();
}
2.3 使用PropertyValuesHolder 创建实例
ValueAnimator和ObjectAnimator除了通过ofInt(),ofFloat(),ofObject()创建实例外,还都有一个ofPropertyValuesHolder()方法来创建实例。
PropertyValuesHolder中有很多函数,有些函数的api等级是11,有些函数的api等级是14和21;
PropertyValuesHolder这个类可以先将动画属性和值暂时的存储起来,后一起执行,在有些时候可以使用替换掉AnimatorSet,减少代码量。
四个构造方法:
- public static PropertyValuesHolder ofFloat(String propertyName, float… values)
- public static PropertyValuesHolder ofInt(String propertyName, int… values)
- public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,Object… values)
- public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe… values)
KeyFrame关键帧 ,一个关键帧必须包含两个原素,第一时间点,第二位置。
构造方法:
/**
* ofFloat
*/
public static Keyframe ofFloat(float fraction)
public static Keyframe ofFloat(float fraction, float value)
/**
* ofInt
*/
public static Keyframe ofInt(float fraction)
public static Keyframe ofInt(float fraction, int value)
例子:
//keyframe
Keyframe keyframe1 = Keyframe.ofFloat(0.0f,0);
Keyframe keyframe2 = Keyframe.ofFloat(0.25f,-30);
Keyframe keyframe3 = Keyframe.ofFloat(0.5f,0);
Keyframe keyframe4 = Keyframe.ofFloat(0.75f, 30);
Keyframe keyframe5 = Keyframe.ofFloat(1.0f,0);
PropertyValuesHolder rotation = PropertyValuesHolder.ofKeyframe("rotation", keyframe1, keyframe2, keyframe3, keyframe4,keyframe5);
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX",1.0f,0.2f,1.0f);
PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat("scaleY",1.0f,0.2f,1.0f);
PropertyValuesHolder color = PropertyValuesHolder.ofInt("BackgroundColor", 0XFFFFFF00, 0XFF0000FF);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mButton, alpha, scaleX, scaleY,color,rotation);
animator.setInterpolator(new OvershootInterpolator());
animator.setDuration(5000).start();
2.4 3.0后View的自带的动画方法
在SDK11的时候,给View添加了animate方法,更加方便的实现动画效果。
在SDK12,SDK16又分别添加了withStartAction和withEndAction用于在动画前,和动画后执行一些操作。当然也可以.setListener(listener)等操作。
// need API 12
mBlueBall.animate()
.alpha(0)
.y(mScreenHeight / 2)
.setDuration(1000)
// need API 12
.withStartAction(new Runnable() {
@Override
public void run() {
Log.e(TAG, "START");
}
})
// need API 16
.withEndAction(new Runnable() {
@Override
public void run() {
Log.e(TAG, "END");
runOnUiThread(new Runnable() {
@Override
public void run() {
mBlueBall.setY(0);
mBlueBall.setAlpha(1.0f);
}
})
// 等同上面使用的withEndAction和withStartAction
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationEnd(Animator animation) { }
@Override
public void onAnimationCancel(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
}).start();
2.5 LayoutAnimator布局动画
布局动画:接下来看看布局动画,主要是针对viewGroup显示子view比如添加删除或显示子view时以什么动画过渡平滑的显示
主要用到两个类,LayoutAnimator
和LayoutTransition
(1)LayoutAnimator设置可控制viewGroup显示子view时以什么样的动画显示平滑出来,但无法控制添加删除子view时仅仅这个子view的动画,这时就要用到(2)
(2)LayoutTransition:可控制子view添加删除时 这个子view平滑过渡的显示
LayoutAnimator
所谓的布局动画是指作用的ViewGroup上,给ViewGroup增加子View时添加一个动画过度效果。
在ViewGroup的xml中添加和这个属性:
android:animateLayoutChanges=”true”
这个效果是android默认的显示的过度效果,我们无法自定义,需要自在定义的过度效果则需要使用LayoutAnimationController类来自定义一个。
代码写法:
/**
* 设置viewGroup加载子view控件显示时的过载动画,就是以什么方式显示比如旋转、平移、淡化等等
* 但是动态添加删除一个view这个不生效,这时就用到LayoutTranstion了
* 第一个参数:需要作用的时间
* 第二个参数:每个子view显示的delay时间
* setOrder:有三个取值
* LayoutAnimationController.ORDER_NORMAL; //顺序显示
* LayoutAnimationController.ORDER_REVERSE;//反显示
* LayoutAnimationController.ORDER_RANDOM//随机显示
*/
private void initLayoutAnim() {
//设置过渡动画
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
//根据具体需求具体定义,也支持集合动画
// AlphaAnimation
// RotateAnimation
// ScaleAnimation
// AnimationSet
sa.setDuration(800);//动画执行时长
//设置动画显示的属性,0.5f是子view间隔显示时的一个延时偏移量单位是s,默认也是0.5f
//即控件动画执行起始的时间间隔了0.5s
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5f);
//按顺序显示,其它两种可查看注释
lac.setOrder(LayoutAnimationController.ORDER_RANDOM);//随机
llAddViewContainer.setLayoutAnimation(lac);
}
xml 写法:
<layoutAnimation
xmlns:android="xxx"
android:delay="0.5"
android:animationOrder="normal"
android:animation="anim/anim_item">
LayoutTransition
过渡的类型一共有四种:
- LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
- LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
- LayoutTransition.DISAPPEARING 当一个View在ViewGroup中消失时,对此View设置的动画
- LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
- LayoutTransition.CHANGE 不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画。
注意:动画到底设置在谁身上,此View还是其他View。
LayoutTransition mTransition = new LayoutTransition();
transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
transition.setAnimator(LayoutTransition.CHANGE_APPEARING));
transition.setAnimator(LayoutTransition.APPEARING,null);
transition.setAnimator(LayoutTransition.DISAPPEARING,null);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,null);
使用布局动画:
// 创建一个GridLayout
mGridLayout = new GridLayout(this);
// 设置每列5个按钮
mGridLayout.setColumnCount(5);
// 添加到布局中
viewGroup.addView(mGridLayout);
//设置动画
mGridLayout.setLayoutTransition(mTransition);
复杂例子:
/**
* 动态添加删除一个view时,view显示的过渡动画效果
* ViewGroup中Layout的动画实现
* 调用 LayoutTransition 对象的 setAnimator() 方法来定义下列动画方式,调用参数是 Animator
* 对象和以下 LayoutTransition 常量:
* (1)APPEARING —— 元素在容器中显现时需要动画显示。
* (2)CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它元素的变化需要动画显示。
* (3)DISAPPEARING —— 元素在容器中消失时需要动画显示。
* (4)CHANGE_DISAPPEARING —— 由于容器中某个元素要消失,其它元素的变化需要动画显示。
*/
private void initLayoutTransition() {
mTransitioner = new LayoutTransition();
llAddViewContainer.setLayoutTransition(mTransitioner);
//view出现时 view自身的动画效果
ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 90F, 0F).
setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING));
mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);
//view 消失时,view自身的动画效果
ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "rotationX", 0F, 90F, 0F).
setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING));
mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animator2);
//view 动画改变时,布局中的每个子view动画的时间间隔
mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);
//为什么这里要这么写?具体我也不清楚,ViewGroup源码里面是这么写的,我只是模仿而已 不这么写貌似就没有动画效果了,所以你懂的!
//view出现时,导致整个布局改变的动画
PropertyValuesHolder pvhLeft =
PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop =
PropertyValuesHolder.ofInt("top", 0, 1);
PropertyValuesHolder pvhRight =
PropertyValuesHolder.ofInt("right", 0, 1);
PropertyValuesHolder pvhBottom =
PropertyValuesHolder.ofInt("bottom", 0, 1);
PropertyValuesHolder animator3 = PropertyValuesHolder.ofFloat("scaleX", 1F, 2F, 1F);
final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, animator3).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING));
changeIn.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
view.setScaleX(1.0f);
}
});
mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
// view消失,导致整个布局改变时的动画
//Keyframe 对象中包含了一个时间/属性值的键值对,用于定义某个时刻的动画状态。
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 2f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation =
PropertyValuesHolder.ofKeyframe("scaleX", kf0, kf1, kf2);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation).
setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
changeOut.addListener(new AnimatorListenerAdapter() {
@Overrid
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
view.setScaleX(1.0f);
}
});
mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
}
2.6 动画监听
ObjectAnimator changeIn;
changeIn.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
view.setScaleX(1.0f);
}
});