Android动画系列:
在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()方法来刷新屏幕,以完成动画效果。
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 | 匀速运动 |
返回值 | 方法 | 注解 |
---|---|---|
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() {
}
***
}
类(接口) | 描述 |
---|---|
IntEvaluator | 用于计算int属性的值的默认计算器 |
FloatEvaluator | 用于计算float属性的值的默认计算器 |
ArgbEvaluator | 用于计算表示为十六进制值的颜色属性值的默认计算器 |
TypeEvaluator | 用于自定义属性值的计算器 |
3.动画的执行动作解析
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()类似,这个可以自行解决,练练手~
此方法要求最低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(TypeEvaluator, Object… values)与ofInt()、ofFloat()并不相同,其不仅有动画属性值作为参数,同时必须传入动画的属性计算器。一方面,由于ofObject()传入的属性值类型不能够确定,从而不能够确定哪种类型的属性值计算器。另一方面,官方提供的动画属性值就那么几种,并不能够满足我们实际的需求,假如传入了一个自定义类或者一系列的String属性值,官方提供的动画属性就不能满足了。而ofInt()、ofFloat()中动画的属性值类型固定,在其内分别内置了IntEvaluaor、FloatEvaluator。既然是这样,不管是使用官方提供的Evaluator还是Valuator都必须指定TypeEvaluator。
具体实例不在写出,详见
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的背景色时,其不是命名属性,此时你只能
ObjectAnimator的属性值参数有且仅有一个,假定此值为结束值,该View必须有getter()方法,以用来获取初始值,而且getter()方法必须是get()的形式。
ObjectAnimator//
.ofFloat(view, "rotationX", 0.0F, 360.0F)//
.setDuration(500)//
.start();
AnimatorUpdateListener是ValueAnimator类的一个成员内部类,其是静态的,且仅声明了一个方法onAnimationUpdate(ValueAnimator)。在动画执行过程中,每次更新都会调用该方法,可以在该回调中手动更新view的属性。
public class ValueAnimator{
***
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
****
}
注:动画执行时,ValueAnimator会计算相关动画且执行动画,但其并不会设置view的属性和对view进行重绘。此时需设置AnimatorUpdateListener监听,并在onAnimationUpdate回调中执行View的invalidate()方法。
对于动画执行过程中,在动画执行过程中,我们总是想执行这样那样的操作,比如在动画结束时,不再显示当前框架,此时我们就得对整个动画的执行进行监听,了解当前动画的执行进度。如果想监听动画,需调用addListener(listener)添加Animator.AnimatorListener。
Animator.AnimatorListener内声明的监听回调方法:
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用于监听动画暂停时的场景,其与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", "动画暂停");
}
});