Android动画系列:
- 补间动画详解
- 帧动画
- LayoutAnimation
- LayoutTransition
- 属性动画 - 基本使用
- 属性动画 - Interpolator(内插器)
- 属性动画 - TypeEvaluator
- 属性动画 - Keyframe
- AnimatorSet
在Android中,动画可以分为三种模式,View Animation、Frame Animation、Property Animation,其中Frame Animation又是View Animation一种特殊形式,只不过它和平移、旋转等常见的View Animation在表现形式上略有不同。
View Animation
View Animation又称为Tween Animation,即补间动画,它通过对场景里的不断做图像变换(平移、缩放、旋转、透明度)从而产生动画,它是一种渐进式动画,并且View Animation支持自定义。
View animation只能应用于View对象,而且只支持一部分属性,如支持缩放旋转而不支持背景颜色的改变。
而且对于View animation,它只是改变了View对象绘制的位置,而没有改变View对象本身,比如,你有一个Button,坐标(100,100),Width:200,Height:50,而你有一个动画使其变为Width:100,Height:100,你会发现动画过程中触发按钮点击的区域仍是(100,100)-(300,150)。
View Animation的四种变换效果对应着Animation的四个子类AlphaAnimation(透明度)、TranslateAnimation(平移)、ScaleAnimation(缩放)、RotateAnimation(旋转)。
常用API
常量
- int ABSOLUTE:指定的尺寸是象素的绝对数目
- int INFINITE:无限重复
- int RELATIVE_TO_PARENT:指定的浮动维度,并应进行动画的高度或宽度对象的与父控件相应相乘
- int RELATIVE_TO_SELF:指定的浮动维度,并应进行动画的高度或宽度对象的与本身相应相乘
- int RESTART:当动画到达末尾和重复次数是无限REPEATER或正值,动画从头重新开始
- int REVERSE:当动画到达末尾和重复次数是无限REPEATER或正值,动画向后(然后再向前)播放
- int START_ON_FIRST_FRAME:可以作为开始时间,指示的开始时间应该是当getTransformation(长,变换)被调用用于第一动画帧的当前时间
- int ZORDER_BOTTOM:动画在其他动画执行后再执行
- int ZORDER_NORMAL:动画保持当前Z顺序
- int ZORDER_TOP:动画优于其他动画执行
常用属性及方法
XML属 性:android:detachWallpaper
关联方法:setDetachWallpaper(boolean)
注释说明:特殊选项窗口动画:如果这个窗口是墙纸的顶部,墙纸不与窗口同时动画
XML属 性:android:duration
关联方法:setDuration(long)
注释说明:动画执行时间
XML属 性:android:fillAfter
关联方法:setFillAfter(boolean)
注释说明:如果fillAfter的值为true,则动画执行后,控件将停留在执行结束的状态
XML属 性:android:fillBefore
关联方法:setFillBefore(boolean)
注释说明:如果fillBefore的值为true,则动画执行后,控件将回到动画执行之前的状态
XML属 性:android:fillEnabled
关联方法:setFillEnabled(boolean)
注释说明:如果设置为true,将fillBefore设置考虑在内
XML属 性:android:interpolator
关联方法:setInterpolator(Interpolator)
注释说明:设置动画的变化速率
XML属 性:android:repeatCount
关联方法:setRepeatCount(int)
注释说明:设置动画重复执行的次数
XML属 性:android:repeatMode
关联方法:setRepeatMode(int)
注释说明:当到达结束和重复计数大于0或无穷大,定义动画行为。
XML属 性:android:startOffset
关联方法:setStartOffset(long)
注释说明:设置动画执行之前的等待时间
XML属 性:android:zAdjustment
关联方法:setZAdjustment(int)
注释说明:允许内容的Z-次序的调整被动画的动画的持续时间
常用方法
- void cancel():取消动画
- boolean hasEnded():动画是否结束
- boolean hasStarted():动画是否开始
- void reset():重置动画
- boolean getTransformation(long currentTime, Transformation outTransformation, float scale) 获取转换的指定时间点
- void start():启动动画首次getTransformation(长,转换)被调用
- void startNow():在当前时间以毫秒为单位启动动画
- boolean getTransformation(long currentTime, Transformation outTransformation, float scale)
- boolean getTransformation(long currentTime, Transformation outTransformation)
- 获取动画指定时间currentTime的Transformation(此方法用于重写)
使用步骤
动态创建Animation
- 创建一个AnimationSet对象(Animation子类);
- 增加需要创建相应的Animation对象;
- 更加项目的需求,为Animation对象设置相应的数据;
- 将Animatin对象添加到AnimationSet对象当中;
- 使用控件对象开始执行AnimationSet。
在XML定义Animation
- 在res文件夹下建立一个anim文件夹;
在文件夹res/anim下创建XML文件,例如res/anim/xx.XML,并首先加入set标签
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator"> </set>
在该标签当中加入rotate,alpha,scale或者translate标签
<alpha android:fromAlpha="1.0" android:toAlpha="0.0" android:startOffset="500" android:duration="500"/>
在代码当中使用AnimationUtils当中装载xml文件,并生成Animation对象。因为Animation是AnimationSet的子类,所以向上转型,用Animation对象接收。
Animation animation = AnimationUtils.loadAnimation( Animation1Activity.this, R.anim.xx); // 启动动画 image.startAnimation(animation);
AlphaAnimation
介绍
AlphaAnimation用于控制View对象的透明度,实现淡入淡出的动画效果。该动画结束后,修改此View的alpha属性。
常用属性
- android:fromAlpha=”1.0” : 动画开始时,View的透明度
- android:toAlpha=”0.0” : 动画结束时,View的透明度
- android:startOffset=”500”:动画开始后,动画延迟多长时间执行
- android:duration=”500”: 动画执行时间
动画实例
XML定义
1.在res/anim/文件夹下创建alpha_tea.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:startOffset="1000">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
/>
</set>
2.加载动画
Animation alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha_tea);
ivTween.startAnimation(alphaAnimation);
代码定义
// 1.创建一个AnimationSet对象,参数为Boolean型
// true表示使用Animation的interpolator,false则是使用自己的
AnimationSet as = new AnimationSet(true);
// 2.创建一个AlphaAnimation对象,参数从完全的透明度,到完全的不透明
// 第一个参数:fromAlpha 开始的透明度
// 第二个参数:toAlpha 结束的透明度
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0f);
// 3.设置动画属性
//设置动画执行的时间
alphaAnimation.setDuration(3000);
// 4.将alphaAnimation对象添加到AnimationSet当中
as.addAnimation(alphaAnimation);
// 5.使用ImageView的startAnimation方法执行动画
ivTween.startAnimation(as);
ScaleAnimation
构造方法
public ScaleAnimation(Context context, AttributeSet attrs)
参数:
context:当前上下文
attrs:xml中读取的属性设置
public ScaleAnimation(float fromX, float toX, float fromY, float toY)
参数:
fromX:x轴的初始值
toX:x轴收缩后的值
fromY:Y轴的初始值
toY:Y轴收缩后的值
public ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY)
参数:
fromX:x轴的初始值
toX:x轴收缩后的值
fromY:Y轴的初始值
toY:Y轴收缩后的值
pivotX:该点关于该对象正在被按比例,指定为绝对数目,其中0是左侧边缘的X坐标(即使对象改变大小,这点保持不变)
pivotY:该点关于该对象正在被按比例,指定为绝对数目,其中0是顶部边缘的Y坐标(即使对象改变大小,这点保持不变)
实际上默认坐标类型为RELATIVE_TO_SELF
public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
参数:
fromX:x轴的初始值
toX:x轴收缩后的值
fromY:Y轴的初始值
toY:Y轴收缩后的值
pivotXType:确定x轴坐标的类型
pivotXValue:x轴的值为 pivotXValue * 相对值(父控件或自身)
pivotYType:确定Y轴坐标的类型
pivotYValue:Y轴的值为 pivotXValue * 相对值(父控件或自身)
常用属性
- android:fromXScale=”1.0” :x轴的初始值
- android:toXScale=”0.0” :x轴收缩后的值
- android:fromYScale=”1.0” :Y轴的初始值
- android:toYScale=”0.0” :Y轴收缩后的值
- android:pivotX=”50%” :该点关于该对象正在被按比例,指定为绝对数目,其中0是左侧边缘的X坐标(即使对象改变大小,这点保持不变)
- android:pivotY=”50%” :该点关于该对象正在被按比例,指定为绝对数目,其中0是顶部边缘的Y坐标(即使对象改变大小,这点保持不变)
- android:duration=”1000” :动画执行时间
动画实例
XML定义
1.在res/anim/文件夹下创建scale_tea.xml
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<scale
android:fromXScale="1.0"
android:toXScale="0.2"
android:fromYScale="1.0"
android:toYScale="0.2"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
2.加载动画
Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale_tea);
ivTween.startAnimation(scaleAnimation);
代码定义
AnimationSet animationSet = new AnimationSet(true);
//参数1:x轴的初始值
//参数2:x轴收缩后的值
//参数3:y轴的初始值
//参数4:y轴收缩后的值
//参数5:确定x轴坐标的类型
//参数6:x轴的值,0.5f表明是以自身这个控件的一半长度为x轴
//参数7:确定y轴坐标的类型
//参数8:y轴的值,0.5f表明是以自身这个控件的一半长度为x轴
ScaleAnimation scaleAnimation = new ScaleAnimation(
1f, 1f,1.5f,0.5f,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
scaleAnimation.setDuration(3000);
animationSet.addAnimation(scaleAnimation);
ivTween.startAnimation(animationSet);
TranslateAnimation
构造方法
public TranslateAnimation(Context context, AttributeSet attrs)
参数:
context:当前上下文
attrs:xml中读取的属性设置
public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
参数:
fromXDelta:动画开始时X坐标
toXDelta:动画结束时X坐标
fromYDelta:动画开始时坐标
toYDelta:动画结束时Y坐标
实际上默认坐标类型为RELATIVE_TO_SELF
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, int fromYType, float fromYValue, int toYType, float toYValue)
参数:
fromXType:动画开始时,指定x坐标维度类型
fromXValue:动画开始时X坐标
toXType:动画结束时,指定x坐标维度类型
toXValue:动画结束时X坐标
fromYType:动画开始时,指定Y坐标维度类型
fromYValue:动画开始时Y坐标
toYType:动画结束时,指定Y坐标维度类型
toYValue:动画结束时Y坐标
动画实例
XML定义
1.在res/anim/文件夹下创建translate_tea.xml
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0%"
android:toXDelta="100%"
android:fromYDelta="0%"
android:toYDelta="100%"
android:duration="2000"/>
</set>
2.加载动画
Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate_tea);
ivTween.startAnimation(translateAnimation);
代码定义
AnimationSet animationSet = new AnimationSet(true);
//参数1~2:x轴的开始位置
//参数3~4:y轴的开始位置
//参数5~6:x轴的结束位置
//参数7~8:x轴的结束位置
TranslateAnimation translateAnimation =
new TranslateAnimation(
Animation.RELATIVE_TO_SELF,0f,
Animation.RELATIVE_TO_SELF,1f,
Animation.RELATIVE_TO_SELF,0f,
Animation.RELATIVE_TO_SELF,1f);
translateAnimation.setDuration(3000);
animationSet.addAnimation(translateAnimation);
ivTween.startAnimation(animationSet);
RotateAnimation
构造方法
RotateAnimation(Context context, AttributeSet attrs)
参数:
context:当前上下文
attrs:xml中读取的属性设置
RotateAnimation(float fromDegrees, float toDegrees)
RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
参数:
fromDegrees:开始时的角度
toDegrees: 动画旋转后的角度
pivotX: 该点关于该物体正在旋转,指定为绝对数目,其中0是左侧边缘的X坐标(俗语就是旋转圆心X坐标)
pivotY: 该点关于该物体正在旋转,指定为绝对数目,其中0是顶部边缘的Y坐标(俗语就是旋转圆心Y坐标)
实际上默认坐标类型为RELATIVE_TO_SELF
RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
参数:
fromDegrees:开始时的角度
toDegrees: 动画旋转后的角度
pivotXType: 确定x轴坐标的类型,有ABSOLUT绝对坐标、RELATIVE_TO_SELF相对于自身坐标、RELATIVE_TO_PARENT相对于父控件的坐标
pivotXValue: x轴的值,0.5f表明是以自身这个控件的一半长度为x轴(俗语就是旋转圆心X坐标)
pivotYType: 确定y轴坐标的类型,有ABSOLUT绝对坐标、RELATIVE_TO_SELF相对于自身坐标、RELATIVE_TO_PARENT相对于父控件的坐标
pivotYValue: y轴的值,0.5f表明是以自身这个控件的一半长度为x轴(俗语就是旋转圆心Y坐标)
动画实例
XML定义
1.在res/anim/文件夹下创建rotate_tea.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="+360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="3000"/>
</set>
2.加载动画
Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate_tea);
ivTween.startAnimation(rotateAnimation);
代码定义
AnimationSet animationSet = new AnimationSet(true);
//参数1:从哪个旋转角度开始
//参数2:转到什么角度
//后4个参数用于设置围绕着旋转的圆的圆心在哪里
//参数3:确定x轴坐标的类型,有ABSOLUT绝对坐标、RELATIVE_TO_SELF相对于自身坐标、RELATIVE_TO_PARENT相对于父控件的坐标
//参数4:旋转中心点,x轴的值,0.5f表明是以自身这个控件的一半长度为x轴
//参数5:确定y轴坐标的类型
//参数6:旋转中心点,y轴的值,0.5f表明是以自身这个控件的一半长度为x轴
RotateAnimation rotateAnimation = new RotateAnimation(0, 360,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
// 设置旋转属性
rotateAnimation.setDuration(3000);
animationSet.addAnimation(rotateAnimation);
ivTween.startAnimation(animationSet);
AnimationSet
AnimationSet提供了一个把多个动画组合成一个组合的机制,并可设置组中动画的时序关系,如同时播放,顺序播放等。
构造方法
AnimationSet(Context context, AttributeSet attrs)
参数
context:当前上下文
attrs:xml中读取的属性设置
AnimationSet(boolean shareInterpolator)
参数
shareInterpolator:是否使用自身的插入器,false使用自身的插入器
常用方法
void addAnimation(Animation a) 加入动画
List<Animation> getAnimations() 获取动画列表
XML标签
android:interpolator:动画插值器。参考Interpolator插值器
android:shareInterpolator:是否和自己子标签共享插值器
动画示例
1.在res/anim/文件夹下创建
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.2"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="+360"
android:pivotX="50%"
android:pivotY="50%"/>
<scale
android:fromXScale="1.0"
android:toXScale="0.2"
android:fromYScale="1.0"
android:toYScale="0.2"
android:pivotX="50%"
android:pivotY="50%"/>
<translate
android:fromXDelta="0%"
android:toXDelta="100%"
android:fromYDelta="0%"
android:toYDelta="100%" />
</set>
2.加载动画
Animation animationSet = AnimationUtils.loadAnimation(this, R.anim.set_tea);
ivTween.startAnimation(animationSet);
fillAfter和fillBefore
每次执行完动画以后,view总是回复到初始位置。从前面介绍可以知道的是,view执行结束以后,可以通过设置fillAfter和fillBefore属性来设置动画执行结束后,view停留的状态。从Animation类源码中可以看出,创建一个Animation对象时,默认fillBefore为true,fillAfter为false,即执行动画结束以后回到view的初始状态。如果你想将view保证为结束的状态,需手动的将fillAfter为true.
如果是独立的Animation,只有setFillAfter有效,设置为true动画结束后保持最后的状态
如果是AnimationSet中的Animation,因为Animation的作用周期可能位于整个AnimationSet动画周期的中间一部分,setFillBefore设置的是在这个动画被执行前是否启用这个动画的第一帧效果填充开始前的动画,setFillAfter设置的是在这个动画结束后是否保留这个动画的最后一帧的效果填充后面的动画,而这两个设置必须同时设置setFillEnable为true
如果想这个AnimationSet结束后保留最后的结果,需要设置AnimationSet的setFillAfter
当setFillEnable为false时,通过查看源码可知在AnimationSet中自身的动画周期不受setFillBefore和setFillAfter控制;当Animation独立存在时,或AnimationSet的setFillAfter为true时,ViewGroup会读取getFillAfter值,如果为true,不clearAnimation,也就保持了最终的状态
- 补间动画执行之后并未改变View的真实布局属性值。切记这一点,譬如我们在Activity中有一个Button在屏幕上方,我们设置了平移动画移动到屏幕下方然后保持动画最后执行状态呆在屏幕下方,这时如果点击屏幕下方动画执行之后的Button是没有任何反应的,而点击原来屏幕上方没有Button的地方却响应的是点击Button的事件。
AnimationListener
AnimationListener是一个监听器,该监听器在动画执行的各个阶段会得到通知,从而调用相应的方法。AnimationListener实际上就是一个接口,包含了onAnimationStart(Animation animation)、onAnimationEnd(Animation animation)、onAnimationRepeat(Animation animation),对应于动画启动、结束、重复。
- onAnimationEnd(Animation animation) 当动画结束时调用
- onAnimationRepeat(Animation animation) 当动画重复时调用
onAniamtionStart(Animation animation) 当动画启动时调用
alphaAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { // 当动画结束时调用 } @Override public void onAnimationEnd(Animation animation) { // 当动画重复时调用 } @Override public void onAnimationRepeat(Animation animation) { // 当动画启动时调用 } });