Android属性动画学习笔记

属性动画基本介绍


Key Classes:
- ValueAnimator : 对所给值进行动画操作,属性动画最核心类。
- ObjectAnimator:对所给值进行动画操作,并将变化作用在对象上。
- AnimatorSet : 对动画进行组合,设置多个动画执行次序。
- TimeInterpolator : 插值器,根据当前时间流逝的百分比来计算出当前属性值改变的百分比。
- TypeEvaluator : 估值器,根据插值器计算的当前属性改变的百分比来计算属性值。插值器和估值器共同决定动画过程。
- ProperityValuesHolder:属性值容器,可以利用它来实现同时对多个属性进行动画,作用类似于AnimatorSet。
- KeyFrame:关键帧,可以指定在某具体时间点([0-1])的属性值。

属性动画基本用法


ValueAnimator的基本使用

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();

以上代码声明一个在1秒时间内从0f变化到1f的过程。
当系统提供的估值器无法满足你的需求时可以使用自定义估值器:

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

ObjectAnimator的基本使用

ObjectAnimator继承自ValueAnimator,它的用法和和功能与ValueAnimator相似,只不过需要指定操作对象及属性:

ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();

以上语句对foo对象的alpha属性在一秒时间内从0f变化到1f。
虽然使用ObjectAnimator要比ValueAnimator方便,但也有一些限制:

  1. 对象要有针对该属性值的set方法
    这是因为ObjectAnimator是使用反射方式调用对象的set方法来对属性进行更新的。当出现这种情况时有三种选择:
    • 给对象添加set方法,如果你有权限的话
    • 用一个类来包装原始对象,间接为其提供set方法。
    • 使用ValueAnimator,监听动画过程,自己实现属性的改变。
  2. 当没提供动画初始值时对象要有该属性值的get方法
    当没提供动画初始值时,ObjectAnimator会通过对象该属性的get方法来获取初始值。

AnimatorSet的基本使用

使用AnimatorSet可以组织多个动画的执行顺序。使用示例如下:

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

以上代码表示动画执行次序为:
先执行动画bounceAnim,然后squashAnim1, squashAnim2, stretchAnim1和 stretchAnim2同时执行,然后执行bounceBackAnim,最后执行fadeAnim。

动画监听器

动画监听器可以监听动画的各个状态以及值。
动画监听器主要有两个:Animator.AnimatorListener与Animator.AnimatorUpdateListener。
AnimatorListener主要有四个回调函数:
- onAnimationStart()–动画开始
- onAnimationEnd()– 动画结束
- onAnimationCancel()– 动画取消
- onAnimationRepeat()– 动画重复

AnimatorUpdateListener只有一个回调函数:
- onAnimatorUpdate()–动画变化的每一帧都会调用该方法,可以在该方法内通过getAnimatedValue()方法获取当前动画值。

添加监听器的方式也很简单,分别调用Animator的addListener()以及addUpdateListener()两个方法可以分别添加上述两种监听器。

属性动画高级用法


该部分主要分析插值器与估值器在动画中的作用以及他们之间的关系。

TimeInterpolator - 插值器

它的作用是根据时间流逝的百分比来计算当前属性值改变的百分比。
Android系统为我们提供了多种插值器,在此就不一一列举了。不过所有的插值器都要实现TimeInterpolator接口, 我们先来看一下它的源码:

    public interface TimeInterpolator {

    /**
     * Maps a value representing the elapsed fraction of an animation to a value that represents
     * the interpolated fraction. This interpolated value is then multiplied by the change in
     * value of an animation to derive the animated value at the current elapsed animation time.
     *
     * @param input A value between 0 and 1.0 indicating our current point
     *        in the animation where 0 represents the start and 1.0 represents
     *        the end
     * @return The interpolation value. This value can be more than 1.0 for
     *         interpolators which overshoot their targets, or less than 0 for
     *         interpolators that undershoot their targets.
     */
    float getInterpolation(float input);
}

可以看出该接口里面只有一个getInterpolation()方法,方法参数input的取值区间[0, 1](0代表动画开始,1代表动画结束),它代表动画时间流逝百分比。方法返回值姑且称之为插值器值fraction,插值器值fraction会传递给估值器,估值器根据fraction和动画开始值以及结束值来计算最终结果。fraction可以大于1也可以小于0,大于1表示动画overshoot他们的目标值,小于0表示属性值unsershoot他们的目标值,OvershootInterpolator插值器在某些时刻fraction就会大于1。

TypeEvaluator- 估值器

它的作用就是根据插值器传入的fraction并且结合动画开始值以及结束值来计算动画最终结果。
所有的估值器都要实现TypeEvaluator接口,我们来看一下它的源码:

public interface TypeEvaluator<T> {

    /**
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value.
     * @param endValue   The end value.
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public T evaluate(float fraction, T startValue, T endValue);

}

同样TypeEvaluator中也只有一个方法,可以看到它需要三个参数:fraction、startValue、 endValue, 分别代表插值器值、动画开始值、动画结束值。动画值就是根据这三个参数确定的。

TimeInterpolator与TypeEvaluator 的关系

经过上面分析我们知道动画值结果就是由TypeEvaluator根据三个参数fraction、startValue、endValue计算出来的,使用数学思维我们可以把动画值看成是fraction的函数:
animatorValue = f(fraction, startValue, endValue)。
而fraction我们有可以看做是input的函数:
fraction = g(input)。
所以动画值就可以看做是插值器和估值器的复合函数:
animatorValue = f(g(input), startValue, endValue)。

补充


最后说一下ProperityValuesHolder以及KeyFrame这两个类的使用方法。

ProperityValuesHolder的基本使用

直接粘贴API demo 中MultiPropertyAnimation类中的代码:

ball = balls.get(1);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(),
              getHeight() - BALL_SIZE);
PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0f);
ObjectAnimator yAlphaBouncer = ObjectAnimator.ofPropertyValuesHolder(ball,
             pvhY, pvhAlpha).setDuration(DURATION/2);
yAlphaBouncer.setInterpolator(new AccelerateInterpolator());
yAlphaBouncer.setRepeatCount(1);
yAlphaBouncer.setRepeatMode(ValueAnimator.REVERSE);

KeyFrame的基本使用

直接粘贴API demo 中MultiPropertyAnimation类中的代码:

ball = balls.get(3);
pvhY = PropertyValuesHolder.ofFloat("y", ball.getY(), getHeight() - BALL_SIZE);
float ballX = ball.getX();
Keyframe kf0 = Keyframe.ofFloat(0f, ballX);
Keyframe kf1 = Keyframe.ofFloat(.5f, ballX + 100f);
Keyframe kf2 = Keyframe.ofFloat(1f, ballX + 50f);
PropertyValuesHolder pvhX = PropertyValuesHolder.ofKeyframe("x", kf0, kf1, kf2);
ObjectAnimator yxBouncer = ObjectAnimator.ofPropertyValuesHolder(ball, pvhY,
           pvhX).setDuration(DURATION/2);
yxBouncer.setRepeatCount(1);
yxBouncer.setRepeatMode(ValueAnimator.REVERSE);

以上两个类的使用很简单,不在多说。


–2016年6月13日00:31:17
–写于宿舍

发布了36 篇原创文章 · 获赞 85 · 访问量 38万+

猜你喜欢

转载自blog.csdn.net/u012719153/article/details/51629395