Android动画系列:
- 补间动画详解
- 帧动画
- LayoutAnimation
- LayoutTransition
- 属性动画 - 基本使用
- 属性动画 - Interpolator(内插器)
- 属性动画 - TypeEvaluator
- 属性动画 - Keyframe
- AnimatorSet
介绍
在Android之补间动画详解已经了解到,View Animation通过重绘View的视图的方式来完成View的动画效果,但View对象本身没有改变。在Android 3.0(API 11),对View添加了新属性和相应的get()和set(),通过在调用set方法设置属性时,其属性更改时会自动调用invalidate()方法来刷新屏幕。
view用拥有set()方法的属性列表:
| 属性 | 描述 |
|---|---|
| translationX / translationY/ translationZ | 这两个属性控制了View所处的位置,它们的值是由layout容器设置的,是相对于坐标原点(0,0左上角)的一个偏移量。translationX和 translationY表示水平方向,translationZ为垂直方向(API 21新添加) |
| rotation,rotationX和rotationY | 控制View绕着轴点(pivotX和pivotY)旋转 |
| scaleX和scaleY | 控制View基于pivotX和pivotY的缩放。 |
| pivotX和pivotY | 旋转的轴点和缩放的基准点,默认是View的中心点 |
| x / y / Z | 用于在其容器中描述视图的最终位置,作为左值和顶值以及translationX和translationY值的和。z为view的高度属性 |
| alpha | 表示view的透明度。默认情况下,此值为1(不透明),值为0表示完全透明(不可见) |
属性动画可以通过更改View的属性,重绘View,更改属性后自动调用invalidate()方法来刷新屏幕,以完成动画效果。
动画特征
- Duration:动画执行时间,默认时间为300 ms
- TimeInterpolator :时间插值,用于计算指定属性的值在当前动画的执行时间
- Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
- Animator Sets:动画集合,可以定义一起播放或顺序播放或在指定延迟后播放,
- Frame refresh delay:帧刷新延迟,对于定义的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态及系统底层定时器所提供的服务。
相关类
- ValueAnimator:值动画执行类,常配合AnimatorUpdateListener使用
- ObjectAnimator:对象动画执行类。
- TimeInterpolator:定义动画插值器
- TypeEvaluator:类型估值,用于设置复杂的动画操作属性的值
- PropertyValuesHolder : 属性存储器,为两个执行类提供更新多个属性的功能
- Keyframe :为 PropertyValuesHolder提供多个关键帧的操作值
- AnimatorSet :一组动画的执行集合类:设置执行的先后顺序,时间等
- AnimatorUpdateListener :动画更新监听
- AnimatorListener :动画执行监听,在动画开始、重复、结束、取消时进行回调。
- AnimatorInflater :加载属性动画的xml文件。
常见的插值器
| Interpolator对象 | 资源ID | 功能作用 |
|---|---|---|
| AccelerateDecelerateInterpolator | @android:animaccelerate_decelerate_interpolator | 先加速再减速 |
| AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
| AnticipateInterpolator | @android:anim/anticipate_interpolator | 先回退一小步然后加速前进 |
| AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 在上一个基础上超出终点一小步再回到终点 |
| BounceInterpolator | @android:anim/bounce_interpolator | 最后阶段弹球效果 |
| CycleInterpolator | @android:anim/cycle_interpolator | 周期运动 |
| LinearInterpolator | @android:anim/linear_interpolator | 匀速运动 |
ValueAnimator
常量
- INFINITE:此值用于setRepeatCount(int)属性,用于无限期地重复动画。实际上其值等于-1,在XML中定义动画无限重复时,通常设置android:repeatCount=”-1”,也就是这样了
- RESTART:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,从头开始
- REVERSE:当动画设置为无限重复或者执行次数大于1时,动画执行结束后,动画反向执行
常用API
| 返回值 | 方法 | 注解 |
|---|---|---|
| void | addUpdateListener(ValueAnimator.AnimatorUpdateListener) | 添加动画更新监听 |
| void | cancel() | 取消当前执行的动画 |
| void | end() | 结束当前动画 |
| void | pause() | 暂停动画 |
| void | reverse() | 反向执行动画 |
| void | start() | 开始动画 |
| void | resume() | 恢复暂停的动画,从暂停的位置开始动画 |
| float | getAnimatedFraction() | 获取当前动画的执行进度 |
| Object | getAnimatedValue() | 获取当前属性值 |
| Object | getAnimatedValue(String) | 通过属性标签获取属性的当前值 |
| boolean | isRunning() | 判断动画是否在执行(动画已开始且运行时间超过所设置的延迟时间,但动画未结束) |
| boolean | isStarted() | 判断动画是否已经开始而且动画未结束 |
| static ValueAnimator | ofArgb(int… values) | 设置颜色值之间切换的动画(比如设置背景颜色) |
| static ValueAnimator | ofFloat(float… values) | 设置在浮点值之间的动画(比如移动) |
| static ValueAnimator | ofInt(int… values) | 设置在整数值之间的动画 |
| static ValueAnimator | ofObject(TypeEvaluator evaluator, Object… values)) | 在values值之间的动画 |
| static ValueAnimator | ofPropertyValuesHolder(PropertyValuesHolder… values) | 设置在PropertyValuesHolders之间执行动画 |
注:
1.getAnimatedValue()和getAnimatedFraction()的区别
getAnimatedValue()的返回值是一个Object,表示当仅有一个属性处于动画状态时,由该ValueAnimator计算的当前属性值。
getAnimatedFraction()的返回值是一个float,其值在0.0和1.0之间,其线性度是由插值器决定的(fraction = t / duration ),而animatedValue值是由相关属性值 * fraction所得的。
2.ValueAnimator的构造函数其实就是一个默认构造函数,并包含动画相关”属性”信息,若采用此种方式创建实例,需通过调用setXX(…)方法设置动画相关属性。当然此时你可以通过静态方法创建ValueAnimator实例,比如ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f),此ValueAnimator设置了相关的动画”属性”
public class ValueAnimator() {
***
public ValueAnimator() {
}
***
}
Evaluators
| 类(接口) | 描述 |
|---|---|
| IntEvaluator | 用于计算int属性的值的默认计算器 |
| FloatEvaluator | 用于计算float属性的值的默认计算器 |
| ArgbEvaluator | 用于计算表示为十六进制值的颜色属性值的默认计算器 |
| TypeEvaluator | 用于自定义属性值的计算器 |
3.动画的执行动作解析
- cancel():取消当前执行的动画,将属性值分配成动画的当前值,调用cancel()方法后,会先触发AnimatorListener的onAnimationCancel方法的执行,然后触发onAnimationEnd方法的执行。
- end():结束当前动画,直接从当前状态跳转到最终的完成状态,将属性值分配成动画的终止值,并触发动画监听器AnimatorListener的onAnimationEnd方法的执行。
- pause():暂停当前执行的动画,将属性值分配成动画的当前值。(API > 19)
- reverse():反向执行动画,但其执行动画的位置为动画的当前位置。但,若动画停留在起始位置,动画将从最后一帧开始;若动画停留在最后一帧,动画将从第一帧开始执行动画。
- start():从第一帧开始执行动画。若设置了动画延迟,动画不会立即执行,待延迟时间过后,动画再执行;若未设置动画延迟,动画会立即执行
- resume():恢复暂停的动画,从暂停的位置开始动画(API > 19)
动画实例
ofFloat/ofInt
ofFloat(float…)方法接收一系列的float类型的值,其内部使用了FloatEvaluator。通过该方法ValueAnimator可以对float值进行动画渐变。现通过ValueAnimator.ofFloat(0.0f, 400f);创建了一个初始值为0.0f,结束值为400f的动画。通过addUpdateListener(ValueAnimator.AnimatorUpdateListener)添加动画监听,AnimatorUpdateListener有一个onAnimationUpdate方法,ValueAnimator会每隔一定时间(默认间隔10ms)计算属性的值,每当计算的时候就会回调onAnimationUpdate方法。在该方法中,我们通过调用ValueAnimator的getAnimatedValue()方法获取到当前动画计算出的属性值,然后我们将该值传入btnProperty的setTranslationX()、setTranslationY()方法中,从而更新了btnProperty的位置,以达到了移动btnProperty的目的。
// 通过静态方法构建一个ValueAnimator对象
// 设置数值集合
mValueAnimator = ValueAnimator.ofFloat(0.0f, 400f);
// 设置作用对象
mValueAnimator.setTarget(btnProperty);
// 设置动画无限循环
mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
// 设置动画执行时间
mValueAnimator.setDuration(4000);
// 添加动画更新监听
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 获取当前值
Float mValue = (Float)animation.getAnimatedValue();
// 动画进度(t/duration)
float fraction = animation.getAnimatedFraction();
Log.d("PropertyActivity", "mValue:" + mValue);
Log.d("PropertyActivity", "fraction:" + fraction + " | t:" + fraction * animation.getDuration());
// 设置横向偏移量
btnProperty.setTranslationX(mValue * 0.5f);
// 设置纵向偏移量
btnProperty.setTranslationY(mValue);
}
});
// 开始执行动画
mValueAnimator.start();
ofInt(Int…)的使用方法与ofFloat()类似,这个可以自行解决,练练手~
ofArgb
此方法要求最低SDK 版本为21,是新添的方法,用于构造颜色值变化的动画。其内部使用了ArgbEvaluator,可以用该方法实现将一个颜色动画渐变到另一个颜色,我们从中可以不断获取中间动画产生的颜色值。我们知道一个int值包含四个字节,在Android中第一个字节代表Alpha分量,第二个字节代表Red分量,第三个字节代表Green分量,第四个字节代表Blue分量,且我们常用16进制表示颜色,这样看起来更明显易懂一些,比如int值0xffff0000表示的红色,0xff00ff00表示的是绿色,最前面的ff表示的是Alpha。ofArgb方法会通过ArgbEvaluator将颜色拆分成四个分量,然后分别对各个分量进行动画计算,然后将四个计算完的分量再重新组合成一个表示颜色的int值,这就是ofArgb方法的工作原理。
现通过静态方法ofArgb(Int…args)创建ValueAnimator对象,设置动画的执行时间为4000ms,设置动画的循环次数为无限循环。在AnimatorUpdateListener监听中,将ArgbEvaluator计算出的颜色的值,通过setBackgroundColor(int)传给btn,设置btn的背景颜色。
//起始颜色为红色
int startColor = 0xffff0000;
//终止颜色为绿色
int endColor = 0xff00ff00;
// 通过静态方法构建一个ValueAnimator对象
// 设置数值集合
mValueAnimator = ValueAnimator.ofArgb(startColor, endColor);
// 设置作用对象
mValueAnimator.setTarget(btnProperty);
// 设置动画无限循环
mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
// 设置动画执行时间
mValueAnimator.setDuration(4000);
// 添加动画更新监听
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int valueColor = (int) animation.getAnimatedValue();
Log.d("PropertyActivity", "mValue:" + valueColor);
btnProperty.setBackgroundColor(valueColor);
}
});
ofObject
ofObject(TypeEvaluator, Object… values)与ofInt()、ofFloat()并不相同,其不仅有动画属性值作为参数,同时必须传入动画的属性计算器。一方面,由于ofObject()传入的属性值类型不能够确定,从而不能够确定哪种类型的属性值计算器。另一方面,官方提供的动画属性值就那么几种,并不能够满足我们实际的需求,假如传入了一个自定义类或者一系列的String属性值,官方提供的动画属性就不能满足了。而ofInt()、ofFloat()中动画的属性值类型固定,在其内分别内置了IntEvaluaor、FloatEvaluator。既然是这样,不管是使用官方提供的Evaluator还是Valuator都必须指定TypeEvaluator。
具体实例不在写出,详见
ObjectAnimator
介绍
ObjectAnimator是ValueAnimator的子类,不同于ValueAnimator的是,其内置了属性值计算器以及拥有对View的命名属性(拥有getter()和setter()的属性)。此时,不必在添加ValueAnimator.AnimatorUpdateListener,ObjectAnimator会自动设置View的属性并自动更新。
实例化的ObjectAnimator类似于ValueAnimator,可以指定对象、对象属性的名称及属性值之间的动画。
ObjectAnimator anim = ObjectAnimator.ofFloat(btn, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();
局限性
由于ObjectAnimator只能自动更新View的命名属性,有一定的局限性。使用ObjectAnimator时应注意:
ObjectAnimator在动画期间自动更新属性,其必须能够调用setter()方法,因而View的动画属性必须有setter()方法。例如当设置View的背景色时,其不是命名属性,此时你只能
- 自定义View,将此属性设置为命名属性
- 改用ValueAnimator,添加AnimatorUpdateListener监听,在回调方法内设置View属性
ObjectAnimator的属性值参数有且仅有一个,假定此值为结束值,该View必须有getter()方法,以用来获取初始值,而且getter()方法必须是get()的形式。
- 动画的属性的getter()和setter()方法中,propertyName的类型必须与ObjectAnimator指定的开始值和结束值的类型一致。
代码实例
ObjectAnimator//
.ofFloat(view, "rotationX", 0.0F, 360.0F)//
.setDuration(500)//
.start();
动画监听
AnimatorUpdateListener
AnimatorUpdateListener是ValueAnimator类的一个成员内部类,其是静态的,且仅声明了一个方法onAnimationUpdate(ValueAnimator)。在动画执行过程中,每次更新都会调用该方法,可以在该回调中手动更新view的属性。
public class ValueAnimator{
***
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
****
}
注:动画执行时,ValueAnimator会计算相关动画且执行动画,但其并不会设置view的属性和对view进行重绘。此时需设置AnimatorUpdateListener监听,并在onAnimationUpdate回调中执行View的invalidate()方法。
Animator.AnimatorListener
对于动画执行过程中,在动画执行过程中,我们总是想执行这样那样的操作,比如在动画结束时,不再显示当前框架,此时我们就得对整个动画的执行进行监听,了解当前动画的执行进度。如果想监听动画,需调用addListener(listener)添加Animator.AnimatorListener。
Animator.AnimatorListener内声明的监听回调方法:
- onAnimationStart(Animator animation):动画开始时回调
- onAnimationCancel(Animator animation):调用cancel()方法手动取消动画时回调
- onAnimationEnd(Animator animation):调用end()方法手动结束动画或者动画正常结束时回调
onAnimationRepeat(Animator animation):动画重复时回调
ValueAnimator mValueAnimator = ValueAnimator.ofFloat(0f, 400f); // 设置作用对象 mValueAnimator.setTarget(btnProperty); // 设置动画无限循环 mValueAnimator.setRepeatCount(ValueAnimator.INFINITE); // 设置动画执行时间 mValueAnimator.setDuration(4000); mValueAnimator.addListener(new Animator.AnimatorListener() { public void onAnimationStart(Animator animation) { Log.d("PropertyActivity", "动画开始"); } @Override public void onAnimationEnd(Animator animation) { Log.d("PropertyActivity", "动画结束"); } @Override public void onAnimationCancel(Animator animation) { Log.d("PropertyActivity", "动画取消"); } @Override public void onAnimationRepeat(Animator animation) { Log.d("PropertyActivity", "动画重复"); } }); mValueAnimator.start();
这样就可以监听动画的开始、结束、被取消、重复等事件,但是有时候我们只需监听其中的某一个事件,比如动画的结束,此时可以添加AnimatorListenerAdapter,取代AnimatorListener。
mValueAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
Log.d("PropertyActivity", "动画结束");
}
});
从AnimatorListenerAdapter源码中可以清晰的看出,AnimatorListenerAdapter是一个抽象类,其实现了Animator.AnimatorListener和Animator.AnimatorPauseListener两个接口,并对接口中的方法空实现。通过添加AnimatorListenerAdapter来监听动画时,没有必要在实现接口的中的方法,只要选择你需要的那个回调并重写即可。
public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,
Animator.AnimatorPauseListener {
public void onAnimationCancel(Animator animation) {
}
public void onAnimationEnd(Animator animation) {
}
public void onAnimationRepeat(Animator animation) {
}
public void onAnimationStart(Animator animation) {
}
public void onAnimationPause(Animator animation) {
}
public void onAnimationResume(Animator animation) {
}
}
Animator.AnimatorPauseListener
Animator.AnimatorPauseListener用于监听动画暂停时的场景,其与pause()、resume()方法一起在API 19新增的API,也就是说添加此监听,SDK版本应在19以上才可以使用。
Animator.AnimatorPauseListener内声明的监听回调方法:
onAnimationPause(Animator animation):动画暂停时回调(调用pause()方法)
onAnimationResume(Animator animation):之前动画暂停,动画回复时回调(调用resume())
mValueAnimator.addPauseListener(new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animation) {
Log.d("PropertyActivity", "动画暂停");
}
@Override
public void onAnimationResume(Animator animation) {
Log.d("PropertyActivity", "动画暂停");
}
});

本文详细介绍了Android属性动画的基本使用,包括动画特征、常见类如ValueAnimator和ObjectAnimator,以及插值器和监听器的运用。通过实例展示了如何使用ofFloat/ofInt/ofArgb/ofObject方法实现不同类型的动画效果,并探讨了ObjectAnimator的局限性。此外,还讨论了AnimatorUpdateListener和AnimatorListener在动画监听中的作用。
641

被折叠的 条评论
为什么被折叠?



