Android动画解析 View动画,帧动画与属性动画

Android的动画形式共分为三种,View动画,帧动画与属性动画。

先对这三种动画做一个概述:

View动画是一种渐进式动画,通过图像的平移、缩放、旋转和透明度等各种渐进式变换完成动画效果。

帧动画是通过不停的切换图片实现动画效果。

属性动画是不停的改变对象的属性来实现动画效果。


View动画:

Android系统提供的View动画分为四类,RotateAnimation,ScaleAnimation,TranslateAnimation,AlphaAnimation,此外,Android还提供了AnimationSet,将四种动画进行组合使用。View动画可以通过setDuration方法,setInterpolator方法,setAnimationListener和setFillAfter方法来设置动画运行的时长,动画的播放速度,对动画进行监听和动画运行结束后View的状态。

View动画还可以为ViewGroup和Activity设置动画。


帧动画:

帧动画就是不停的切换图片来实现动画效果,就如同小人书,但比较容易出现OOM,所以在使用时,需要注意图片大小。


属性动画:

View动画的那四种效果有很明显的缺点,绘制出来的效果其实并没有真正改变View的属性,即left、top、right和bottom的值,只是系统临时绘制的结果。这样View的点击位置并没有发生变化。针对这个问题,从Android3.0开始属性动画应运而生。

属性动画本质是通过改变新增的属性(如平移translationX/Y、缩放scaleX/Y、旋转rotationX/Y等)并刷新屏幕来实现动画效果,并且实现点击位置的实时改变。但是属性动画仍然不会修改原始的上下左右四个值。最后需要注意的是,属性动画不止用于View,还可以用于任何对象。

ValueAnimator是整个属性动画机制中最核心的一个类,属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等,确实是一个非常重要的类。


ObjectAnimator是我们最常接触的类,它继承自ValueAnimator。由于ValueAnimator只是对值进行了一个平滑的动画过渡,我们在实际中应用的场景并不多。而ObjectAnimator就不同了,它可以直接对任意对象的任意属性进行动画操作,例如 alpha, rotation, translationX, translationY, scaleX, scaleY等。我们同样可以使用AnimationSet来将不同属性的动画进行组合。

Animator监听器

Animator类中提供了addListener方法来对属性动画进行监听,这个方法接收一个AnimationListener,我们只需要实现AnimationListener就可以监听动画的各种事件了。我们已经知道了ObjectAnimator继承自ValueAnimator,而ValueAnimator又继承自Animator,因此,ObjectAnimator与ValueAnimator都可以使用addListener方法来对动画进行监听。

    anim.addListener(new AnimatorListener() {  
        @Override  
        public void onAnimationStart(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationRepeat(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationEnd(Animator animation) {  
        }  
      
        @Override  
        public void onAnimationCancel(Animator animation) {  
        }  
    });  

但有时候我们并不会使用AnimationListener中的所有方法,这就会造成出现很多空方法的状况。这种情况下,我们可以使用AnimationListenerAdapter,里面已经定义了每个方法的空方法,我们只需要重写我们需要的方法就可以了。


Animator类还可添加更新监听器,如下,

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                Point point = (Point)animation.getAnimatedValue();
                circle.x = point.getX();
                circle.y = point.getY();
                circle.invalidate();
            }
        })

在AnimatorUpdateListener接口中的onAnimationUpdate方法中,调用animation.getAnimatedValue()方法即可获得Animator更新后的最新属性(ObjectAnimator)或值(ValueAnimator)。


插值器TimeInterpolator与估值器TypeEvaluator

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);
}

public interface TypeEvaluator<T> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @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);

}

插值器TimeInterpolator是用来控制动画的节奏快慢的,估值器TypeEvaluator是用来控制动画的实现的。


TimeInterpolator接口中的getInterpolation方法接收一个float变量input,input的取值范围为0~1,表示当前运行了的时间在设定时间中的位置,返回值即为TypeEvaluator接口中evaluate方法中的参数fraction。evaluate方法根据传入的fraction,起始值startValue,结束值endValue来控制动画。ofFloat与ofInt默认使用FloatEvaluator类和IntEvaluator类。

public class FloatEvaluator implements TypeEvaluator<Number> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>float</code> or
     *                   <code>Float</code>
     * @param endValue   The end value; should be of type <code>float</code> or <code>Float</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Float evaluate(float fraction, Number startValue, Number endValue) {
        float startFloat = startValue.floatValue();
        return startFloat + fraction * (endValue.floatValue() - startFloat);
    }
}

public class IntEvaluator implements TypeEvaluator<Integer> {

    /**
     * This function returns the result of linearly interpolating the start and end values, with
     * <code>fraction</code> representing the proportion between the start and end values. The
     * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
     * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
     * and <code>t</code> is <code>fraction</code>.
     *
     * @param fraction   The fraction from the starting to the ending values
     * @param startValue The start value; should be of type <code>int</code> or
     *                   <code>Integer</code>
     * @param endValue   The end value; should be of type <code>int</code> or <code>Integer</code>
     * @return A linear interpolation between the start and end values, given the
     *         <code>fraction</code> parameter.
     */
    public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
        int startInt = startValue;
        return (int)(startInt + fraction * (endValue - startInt));
    }
}

从上面FloatEvaluator和IntEvaluator的evaluator方法,我们可以很清晰的看出,只是将简单的计算了startValue与endValue中间的fraction处的值返回即可。

如果是ofObject方法,则需要自己定义TypeEvaluator,只需实现TimeInterpolator接口即可。

如果不自定义TimeInterpolator,默认getInterpolation方法默认直接返回input。我们可以使用setInterpolator方法设置自定义的TimeInterpolator。根据input计算不同的fraction,便可控制动画运行的速率变化。


好了,属性动画就是这么简单,你学会了吗?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章