安卓三种动画小结

安卓中,动画可以分为三类。逐帧动画,补间动画,属性动画。稍微小结下,我对这三个动画的认识。

逐帧动画

AnimationDrawble,所以逐帧动画,其实是一种图像。通过设置ImageView类的background好或者src从代码和xml两个方式上载入。

####纯代码
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
frameAnimation.start();

xml定义

<animation-list android:id="@+id/selected"     android:oneshot="false">
<item android:drawable="@drawable/    wheel0" android:duration="50" />
<item android:drawable="@drawable/wheel1" android:duration="50" />
<item android:drawable="@drawable/wheel2" android:duration="50" />
 </animation-list>

补间动画

补间:开发者只需要给出动画的起始和结束帧状态,中间的帧交由安卓系统计算和补齐。抽象类Animation是补间动画的基类。同样可以分为xml和纯代码两种方式显示。补间动画无法实现动画无限重复播放。

涉及的API

AlphaAnimation,ScaleAnimation,RotateAnimation,TranslateAnimation,AnimationSet,Interpolator(差值接口),TimeInterpolator,Transformation,Camera(三维图形变换,类似Matrix)

Animation animation = AnimationUtils.loadAnimation(Context context,int id)

实现自定义补间动画

继承Animation,重写initalize()方法和applyTransformation(float interpolatedTime,Transformation t)方法

  • interpolatedTime:代表了动画的时间进行比,不管动画实际的持续时间如何,当动画播放时,该参数总是自动从0变化到1.
  • Transformation 该参数代表了补间动画在不同时刻对图形或组件的变形程度。
applyTransformation方法的参考代码:
camera.save();
camera.rotateY(360 *interpolatedTime);
Matrix matrix = transformation.getMatrix();
camera.getMatrix(matrix);
matrix.preTranslate(-centerX,-centerY);
camera.restore();

属性动画

属性动画主要有两方面组成:1计算各帧的相关属性值 2为指定对象设置这些计算后的值。
对象的属性名称有:rotationX,rotationY,scaleX,scaleY,alpha,translationX,translationY
监听事件 ValueAnimator.AnimatorUpdateListener , Animator.AnimatorListener

涉及的API

Animator:属性动画的基类。

  • ValueAnimator: 负责第一方面的内容。因此第二方面,为指定对象设置属性值须由程序员通过监听来完成。
  • ObjectAnimator,是ValueAnimator的子类,使用起来更简单。
  • AnimatorSet(属性动画组合),它是Animator的子类,用于组合多个Animator,指定播放顺序。

Evaluator和TypeEvaluator

Evaluator 计算器,控制属性动画如何计算属性值。TypeEvaluator 计算器接口,通过实现该接口来实现自定义计算器。

  • IntEvaluator
  • FloatEvaluator
  • ArgbEvaluator
  • PointFEvaluator
  • RectEvaluator

ValueAnimator的使用

基本用法

  • 调用ValueAnimator的ofInt(),ofFloat()或ofObject静态方法创建
  • 设置持续时间,插值方式,动画模式等属性
  • 注册监听器AnimationUpdateListerner,在监听方法里,通过getAnimatedValue()方法,把当前帧的值应用到所需要的对象上。
  • start()启动动画

如果getAnimatedValue()返回的不是系统默认的值,借助TypeEvaluator接口,用系统自带的实现类,如PointFEvaluator,FloatArrayEvaluator,或者自己实现TypeEvaluetor,重写evaluator方法。

代码如下:

valueAnimator.setObjectValues(new PointF(0, 0));
valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
    @Override
    public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
        Log.e("evaluate","fraction="+fraction + " startValue="+startValue +" endValue=" + endValue);
        PointF pointF = new PointF();
        pointF.x = 200 * fraction * 3;
        pointF.y = (float) (0.5 * 10 * 200 * fraction * fraction);
        return pointF;
    }
});
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            PointF pointF = (PointF) animation.getAnimatedValue();
            ball.setTranslationX(pointF.x);
            ball.setTranslationY(pointF.y);
        }
    });

ObjectAnimator的使用

继承自ValueAnimator,完成了属性动画的两个方面,所以可以直接把动画应用到对象上。

注意事项

  • 该对象存在对应属性的setter方法。
  • 如果只提供一个值,则该值被认为是结束值,此时需要提供getter方法。
  • 如果该对象的setter方法不会自动调用invalidate()方法,则需要在onAnimationUpdate()监听方法里调用invalidate()刷新屏幕。

xml定义属性动画

<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
    android:duration="600"
    android:interpolator="@android:interpolator/accelerate_decelerate"
    android:propertyName="alpha"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:valueFrom="1"
    android:valueTo="0"
    android:valueType="floatType"
    />

Animator animator = AnimatorInflator.loadAnimator(Context context,int resId);

多个属性动画同时播放的实现

通过AnimatorSet

AnimatorSet s = new Animatorset();
s.play(animator1).before(animator2);
s.paly(animator2).befor(animator3);

2、ValueAnimator,ObjectAnimater的AnimatorUpdateListener监听方法onAnimationUpdate里,调用对象的多个属性setter即可

3、借助PropertyValuesHolder

PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha",1f,0f);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX",1f,0f);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f);
ObjectAnimator animator1 = ObjectAnimator.ofPropertyValuesHolder(txt,holder1, holder2, holder3);
animator1.setDuration(800);
animator1.setInterpolator(new AccelerateDecelerateInterpolator());
animator1.setRepeatMode(ValueAnimator.REVERSE);
animator1.setRepeatCount(ValueAnimator.INFINITE);
animator1.setStartDelay(1000);
animator1.start();

借助ViewPropertyAnimator实现同时播放动画

//need API12  
    mBlueBall.animate()//  
            .alpha(0)//  
            .y(mScreenHeight / 2).setDuration(1000)  
            // need API 12  
            .withStartAction(new Runnable()  
            {  
                @Override  
                public void run()  
                {  
                    Log.e(TAG, "START");  
                }  
                // need API 16  
            }).withEndAction(new Runnable()  
            {  

                @Override  
                public void run()  
                {  
                    Log.e(TAG, "END");  
                    runOnUiThread(new Runnable()  
                    {  
                        @Override  
                        public void run()  
                        {  
                            mBlueBall.setY(0);  
                            mBlueBall.setAlpha(1.0f);  
                        }  
                    });  
                }  
            }).start(); 

等效于:
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat(“alpha”, 1f,
0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat(“y”, 0,
mScreenHeight / 2, 0);
ObjectAnimator.ofPropertyValuesHolder(mBlueBall, pvhX, pvhY).setDuration(1000).start();

参考资料

  1. 《疯狂安卓讲义》
  2. Android 属性动画(Property Animation) 完全解析 (下)