Android属性动画 Property Animation

3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变,比如无论你在对话中如何缩放Button的大小,Button的有效点击区域还是没有应用动画时的区域,其位置与大小都不变。

    Animator:它提供了创建animation最基本的结构,基本上不会直接地用到这个类,要使用这个类,必须继承它并实现需要的功能。
    ValueAnimator:property animation主要的时间引擎,它计算了各个帧的属性值。它包括所有核心功能:计算每个帧的相关内容,负责接收更新事件,按属性值的类型自定义计算规则。一个动画需要完成两大块内容:计算各帧的相关内容和并为对象设置这些计算后的值。ValueAnimator不负责第二块内容,因此你必须由ValueAnimator监听计算值的更新并修改对象相关属性值。
    ObjectAnimator:ValueAnimator子类,它允许你设置一个对象的属性来完成动画。ObjectAnimator更加常用,因为使用它来建立动画会更加简单。然而,有时你需要用到ValueAnimator,因为ObjectAnimator会有一些限制。
    AnimatorSet:把多个Animator捆绑在一起,可以让他们同时播放,或按顺序地播放、或延时一段时间播放。

Evaluators用于告诉Property Animation系统如何去计算属性值。Property Animation系统提供了下面的一些Evaluator:

    IntEvaluator:用于计算Int类型属性值的计算器。
    FloatEvaluator:用于计算Float类型属性值的计算器。
    ArgbEvaluator:用于计算以16进制形式表示的颜色值的计算器。
    TypeEvaluator:一个计算器接口,它允许你创建你自己的计算器。如果你正在计算一个对象属性并不是int,float或者颜色值类型的,那么你必须实现TypeEvaluator接口去指定如何去计算对象的属性值。

在android.view.animation包中定义的TimeInterpolator:

    AccelerateDecelerateInterpolator:先加速后减速的插值器
    AccelerateInterpolator:加速插值器
    AnticipateInterpolator:先往变化的相反方向回退,然后甩到尾值的插值器
    AnticipateOvershootInterpolator:先往变化的相反方向回退,然后甩到尾值并越过尾值,再返回到尾值。
    BounceInterpolator: 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
    CycleInterpolator:指定重复次数的插值器
    DecelerateInterpolator:减速插值器
    LinearInterpolator:线性(匀速)插值器
    OvershootInterpolator:超过尾值再返回到尾值的插值器
    TimeInterpolator:用于实现自己的插值器的接口

ObjectAnimator与ValueAnimator的区别是ObjectAnimator可以直接地把动画过程中计算出来的的值应用到一个具体对象的属性上,而ValueAnimator需要另外注册一个监听器来完成这个工作。
一个很简单的让按钮淡入的效果来进行对比一下
ValueAnimator 实现:

         animation = ValueAnimator.ofFloat(0f , 1.0f); 
         animation.setDuration(1000); 
         animation.addUpdateListener(new AnimatorUpdateListener() { 
    @Override 
    public void onAnimationUpdate(ValueAnimator animation) { 
        button01.setAlpha((Float) animation.getAnimatedValue()); 
    } 
    ); 

ObjectAnimator 实现:

    //button01 操作的对象. 
    //对象的属性名(String) 
    animation = ObjectAnimator.ofFloat(button01, "Alpha", 0f , 1.0f); 
    animation.setDuration(1000); 

为了让ObjectAnimator能正常地运作,你还需要注意下面几点:

    要为对应的对象提供setter方法,如上例中需要为button01对象添加setAlpha(float value)方法。在不能修改对象源码的情况下,要不先对对象进行封装(extends),或者使用ValueAnimator。
    如果ObjectAnimator的工厂方法中的values... 参数提供了一个值(原本需要提供起始值和结束值),那么该值会被认为是结束值。起始值需要通过对象的getter方法提供,因此,在这种情况下,还需要提供对应属性的getter方法。
    Java代码
        ObjectAnimator.ofFloat(targetObject, "propName", 1f) 
    如果动画的对象是View,那么就可能需要在onAnimationUpdate()回调函数中调用View.invalidate()方法来刷新屏幕的显示。比如说,设置Drawable对象的color属性。但是,View中的所有setter方法,如setAlpha()andsetTranslationX()会自动地调用invalidate()方法,因此不需要额外地调用invalidat

可以看到ObjectAnimator是直接对对象进行操作,但是需要对象提供相应的 Seter/Geter 方法.而ValueAnimator需要注册一个AnimatorUpdateListener.根据getAnimatedValue 自由的进行操作.


使用AnimatorSet编排多个Animator

    mAnimationSet = new AnimatorSet(); 
    mAnimationSet.play(fadeOut).before(fadeIn); 
    mAnimationSet.play(fadeIn).with(ScaleX); 
    mAnimationSet.play(ScaleY).after(ScaleX); 

执行顺序:fadeOut > fadeIn && ScaleX > ScaleY.  刚才在测试的时候发现不能使用CycleInterpolator 进行循环.


一个按钮横向移动到父类容器的右侧的示例:


    @Override 
    public void onWindowFocusChanged(boolean hasFocus) { 
            
        Log.i(TAG, "button01.getRight():" +button01.getRight()); 
         
        //获取button01父类宽度. 
        View view = (View)button01.getParent(); 
           Log.i(TAG, "view.getRotationY():" +view.getRight()); 
            
           ObjectAnimator right = ObjectAnimator.ofFloat(button01, "x", 0 , view.getRight() - button01.getRight()); 
           right.setDuration(1000); 
           //先往变化的相反方向回退,然后甩到尾值并越过尾值,再返回到尾值。 
           right.setInterpolator(new AnticipateOvershootInterpolator()); 
            
           mAnimationSet.play(right); 
            
        super.onWindowFocusChanged(hasFocus); 
    } 

猜你喜欢

转载自typ1984.iteye.com/blog/1717494