基础篇-动画机制-Property Animator源码解析

2.1 Property Animation 的工作方式

Property Animation 动画有两个步聚:
1.计算属性值,Interpolator插值器)和 Evaluators(估值器)共同决定目标值。
2.为目标对象的属性设置属性值,反射或自定义方法执行,即应用和刷新动画


2.1.1 属性动画流程图

过程一:计算已完成动画分数 elapsed fraction 为了执行一个动画,你需要创建一个 ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用 start 后的整个动画过程中, ValueAnimator 会根据已经完成的动画时间计算得到一个 0 到 1 之间的分数,代表该动画的已完成动画百分比。0 表示 0%,1 表示 100%。


过程二:计算插值(动画变化率)interpolated fraction 当 ValueAnimator 计算完已完成动画分数后,它会调用当前设置的 TimeInterpolator,去计算得到一个 interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中, 函数映射动画时间执行节点,定义动画变化率

过程三:计算属性值 当插值分数计算完成后,ValueAnimator 会根据插值分数调用合适的 TypeEvaluator 去计算运动中的属性值,其实是定义数据结构和属性值的计算方法,最终根据动画变化率两者共同决定动画的运动

2.2 核心类关系

2.2.1 Interpolators

插值器:时间的函数,定义了动画的变化律, 和传统动画,插值器一样。
插值器只需实现一个方法: getInterpolation(float input),其作用就是把 0 到 1 的 elapsed fraction 变化映射到另一个 interpolated fraction。 Interpolator 接口的直接继承自 TimeInterpolator,内部没有任何方法,而 TimeInterpolator只有一个 getInterpolation方法,所以所有的插值器只需实现 getInterpolation方法即可。
传入参数是正常执行动画的时间点,返回值是调用者真正想要它执行的时间点。传入参数是{0,1},返回值一般也是{0,1}。{0,1}表示整段动画的过程。中间的 0.2、0.3 等小数表示在整个动画(原本是匀速的)中的位置,其实就是一个比值。如果返回值是负数,会沿着相反的方向执行。如果返回的是大于 1,会超出正方向执行。也就是说,动画可能在你指定的值上下波动,大多数情况下是在指定值的范围内。
getInterpolation(float input)改变了默认动画的时间点 elapsed fraction,根据时间点 interpolated fraction 得到的是与默认时间点不同的属性值,插值器的原理就是通过改变实际执行动画的时间点,提前或延迟默认动画的时间点来达到加速/减速的效果。动画插值器目前都只是对动画执行过程的时间进行修饰,并没有对轨迹进行修饰。

简单点解释这个方法,就是当要执行 input 的时间时,通过 Interpolator 计算返回另外一个时间点,让系统执行另外一个时间的动画效果。

2.2.2 Evaluators(估值器)

Evaluators 告诉属性动画系统如何去计算一个属性值。它们通过 Animator 提供的动画的起始和结束值去计算一个动画的属性值。 属性系统提供了以下几种 Evaluators: 1.IntEvaluator
2.FloatEvaluator
3.ArgbEvaluator
这三个由系统提供,分别用于计算 int,float,color 型(十六进制)属性的计算器

4.TypeEvaluator
一个用于用户自定义计算器的接口,如果你的对象属性值类型,不是 int,float,或者 color 类型,你必须实现这个接口,去定义自己的数据类型。


TypeEvaluator 接口只有一个方法,就是 evaluate() 方法,它允许你使用的 animator 返回一个当前动画点的属性值。

TimeInterpolator 和 TypeEvaluator 的区别
首先明确动画属性值的计算包括三步,其中第二步和第三步分别需要借助TimeInterpolatorTypeEvluator完成。

TypeEvaluator所做的是根据数据结构计算最终的属性值,允许你定义自己的数据结构,这是官方对它的真正定义,如果你所定义的属性值的数据类型不是 float、int、color 类型,那么你需要实现 TypeEvaluator 接口的evaluate()方法,自己进行属性值的计算

Interpolator更倾向于你定义一种运动的变化率,比如匀速、加速、减速等,官方对 Interpolator 的定义也确实是这样的:

A time interpolator defines the rate of change of an >animation. This allows animations to have non-linear >motion, such as acceleration and deceleration.


对于自定义高级动画时,弄清 TimeInterpolatorTypeEvaluator非常重要,如果你希望要自定义自己的动画,那么这两个函数肯定是关键部分, 一个是定义动画变化率,一个是定义数据结构和属性值计算方式,两者共同决定了一个动画的运动。
2.2.3 ValueAnimator

属性动画中的主要的时序引擎,如动画时间,开始、结束属性值,相应时间属性值计算方法等。包含了所有计算动画值的核心函数。也包含了每一个动画时间上的细节,信息,一个动画是否重复,是否监听更新事件等,并且还可以设置自定义的计算类型。


使用 ValueAnimator 实现动画需要手动在UpdateListioner()中执行更新操作:

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.addUpdateListener(new AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.i("update", ((Float) animation.getAnimatedValue()).toString());
 int curValue = (int)animation.getAnimatedValue(); 
        tv.layout(curValue,curValue,curValue+tv.getWidth(),curValue+tv.getHeight()); 
   
    }
});
animation.setInterpolator(new CycleInterpolator(3));
animation.start();

总而言之就是两点:

  • ValueAnimator 只负责对指定的数字区间进行动画运算
  • 我们需要对运算过程进行监听,然后自己对控件做动画操作

关于监听器一:AnimatorUpdateListener 就是监听动画的实时变化状态,在 onAnimationUpdate(ValueAnimator animation)中的 animation 表示当前状态动画的实例。
关于监听器二: AnimatorListener监听关键节点事件; 在 AnimatorListener 中,主要是监听 Animation 的四个状态,start、end、cancel、repeat;当动画开始时,会调用 onAnimationStart(Animator animation)方法,当动画结束时调用 onAnimationEnd(Animator animation),当动画取消时,调用 onAnimationCancel(Animator animation)函数,当动画重复时,会调用 onAnimationRepeat(Animator animation)函数。 添加 AnimatorListener 的方法是 addListener(AnimatorListener listener) ; 
  • /** 
     * 监听器一:监听动画变化时的实时值 
     */ 
    public static interface AnimatorUpdateListener { 
        void onAnimationUpdate(ValueAnimator animation); 

    //添加方法为:public void addUpdateListener(AnimatorUpdateListener listener) 
    /** 
     * 监听器二:监听动画变化时四个状态 
     */ 
    public static interface AnimatorListener { 
        void onAnimationStart(Animator animation); 
        void onAnimationEnd(Animator animation); 
        void onAnimationCancel(Animator animation); 
        void onAnimationRepeat(Animator animation); 

    //添加方法为:public void addListener(AnimatorListener listener) 
AnimatorUpdateListener 监听器使用 animation.getAnimatedValue()函数拿到 Evaluator 中返回的数字值。 讲了这么多,Evaluator  其实就是一个转换器,他能把 Interpolator生成的 小数进度或其他的实际执行时间点,转换成对应的数值位置,
public void  setEvaluator ( TypeEvaluator value {
    if  (value  !=  null  &&  mValues  !=  null  &&  mValues . length  0 {
        mValues [ 0 ] .setEvaluator (value ) ;
    }
}


2.2.4 ObjectAnimator

继承自 ValueAnimator ,允许你指定要进行动画的对象以及该对象的一个或多个属性。该类会根据计算得到的新值,通过反射ReflectiveProperty更新对象已经存在的属性值 ,或者调用自定义属性的set方法更新。大多数的情况,你使用 ObjectAnimator 就足够了,因为它使得目标对象动画值的处理过程变得简单,不用再向 ValueAnimator 那样自己写动画更新的逻辑。但 ObjectAnimator 有一定的限制,比如它需要目标对象的属性提供指定的处理方法,这个时候你需要根据自己的需求在 ObjectAnimator ValueAnimator 中做个选择了,看哪种实现更简便。

ObjectAnimator的自动更新功能,依赖于属性身上的settergetter方法,所以为了让ObjectAnimator能够正确的更新属性值,你必须遵从以下规范:

  1. 该对象的属性必须有getset方法(方法的格式必须是驼峰式),方法格式为 set(),因为 ObjectAnimator 会自动更新属性,它必须能够访问到属性的setter方法,比如属性名为foo,你就需要一个setFoo()方法,如果 setter 方法不存在,你有三种选择:
    a.添加 setter 方法
    b.使用包装类。通过该包装类通过一个有效的 setter 方法获取或者改变属性值的方法,然后应用于原始对象,比如 NOA 的AnimatorProxy
    c.使用 ValueAnimator 代替

(这 3 点的意思总结起来就是一定要有一个setter方法,让ObjectAnimator能够访问到)

  1. 如果你为 ObjectAnimator 的工厂方法的可变参数只传递了一个值,那么会被作为动画的结束值。

  2. 注意,属性的getter方法和setter方法必须必须是相对应的,比如你构造了一个如下的ObjectAnimator,那么gettersetter方法就应该为:

    targetObject.setPropName(float) 和 targetObject.getPropName(float) :
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
    
    
    
  3. 根据动画的目标属性或者对象不同,你可能需要调用某一个 View 的invalidate方法,根据新的动画值去强制屏幕重绘该 View。可以在onAnimateonUpdate()回调方法中去做。比如,对一个 Drawable 的颜色属性进行动画,只有当对象重绘自身的时候,才会导致该属性的更新,(不像平移或者缩放那样是实时的)。一个 View 的所有 setter 属性方法,比如setAlpha()setTranslationX()都可以适当的更新 View。因此你不需要在重绘的时候为这些方法传递新的值。更多关于 Listener 的信息,可以参考第四部分 Animation Listeners。

简单总结下: 当你不希望向外暴露 Setter 方法的时候,或者希望获取到动画值统一做处理的话,亦或只需要一个简单的时序机制(拥有动画的各种值)的话,那么你可以选择使用 ValueAnimator ,它更简单。如果你就是希望更新动画,为了简便,可以使用 ObjectAnimator ,但自定义的属性必须有 setter getter 方法,并且它们必须都是标准的驼峰式(确保内部能够调用),必须有结束值。你可以实现 Animator.AnimatorListener 接口根据自己的需求去更新 View。

2.2.5 AnimatorSet

提供组合动画能力的类。并可设置组中动画的时序关系,如同时播放、有序播放或延迟播放。 首先,AnimatorSet 针对 ValueAnimator 和 ObjectAnimator 都是适用的,但一般而言,我们不会用到 ValueAnimator 的组合动画,所以我们这篇仅讲解 ObjectAnimator 下的组合动画实现。 在 AnimatorSet 中直接给为我们提供了两个方法 playSequentially 和 playTogether,playSequentially 表示所有动画依次播放,playTogether 表示所有动画一起开始。
3、playSequentially,playTogether 真正意义

想必大家都看到赛马,在赛马开始前,每个马都会被放在起点的小门后面,到点了,门打开,马开始一起往前跑。而假如我们把每匹马看做是一个动画,那我们的 playTogether 就相当于赛马场里每个赛道上门的意义(当比赛开始时,每个赛道上的门会打开,马就可以开始比赛了);也就是说,playTogether 只是一个时间点上的一起开始,对于开始后,各个动画怎么操作就是他们自己的事了,至于各个动画结不结束也是他们自已的事了。所以最恰当的描述就是门只负责打开,打开之后马咋跑,门也管不着,最后,马回不回来跟门也没啥关系。门的责任只是到点就打开而已。放在动画上,就是在激活动画之后,动画开始后的操作只是动画自己来负责。至于动画结不结束,也只有动画自己知道。 
而 playSequentially 的意义就是当一匹马回来以后,再放另一匹。那如果上匹马永远没回来,那下一匹马也永远不会被放出来。 
放到动画上,就是把激活一个动画之后,动画之后的操作就是动画自己来负责了,这个动画结束之后,再激活下一个动画。如果上一个动画没有结束,那下一个动画就永远也不会被激活。

playTogether 和 playSequentially 在开始动画时,只是把每个控件的动画激活,至于每个控件自身的动画是否具有延时、是否无限循环,只与控件自身的动画设定有关,与 playTogether、playSequentially 无关。playTogether 和 playSequentially 只负责到点激活动画。

AnimatorSet 监听器



public static interface AnimatorListener { /**

  • 当 AnimatorSet 开始时调用 */ void onAnimationStart(Animator animation);

    /**

  • 当 AnimatorSet 结束时调用 */ void onAnimationEnd(Animator animation);

    /**

  • 当 AnimatorSet 被取消时调用 */ void onAnimationCancel(Animator animation);

    /**

  • 当 AnimatorSet 重复时调用,由于 AnimatorSet 没有设置 repeat 的函数,所以这个方法永远不会被调用 */ void onAnimationRepeat(Animator animation); }

好像这个 listenner 和 ValueAnimator 的一模一样啊。不错,确实是一模一样,因为 ValueAnimator 和 AnimatorSet 都派生自 Animator 类,而 AnimatorListener 是 Animator 类中的函数。 监听器的用法并不难,难点在于,我们 AnimatorSet 中的监听器,监听的 AnimatorSet 本身的动作,还是它内部的每个动画的动作?在 AnimatorSet 代码注释中我们已经提到,它监听的是 AnimatorSet 的过程,所以只有当 AnimatorSet 的状态发生变化时,才会被调用。

AnimatorSet 的监听函数也只是用来监听 AnimatorSet 的状态的,与其中的动画无关; 
取消,会停止所有的动画,AnimatorSet执行end,repeat是动画组合的循环,

2.2.6 ViewPropertyAnimator

可以方便的为某个 View 的多个属性添加并行的动画,只使用一个ViewPropertyAnimator对象就可以完成。它的行为更像一个ObjectAnimator,因为它修改的是对象的实际属性值。但它为一次性给多个属性添加动画提供了方便,而且使用ViewPropertyAnimator的代码更连贯更易读。
下面的代码段分别展示了使用多个ObjectAnimator对象、一个ObjectAnimator对象、ViewPropertyAnimator同时为一个 View 的 X 和 Y 属性添加动画的示例:

多个 ObjectAnimator 结合 AnimatorSet 实现

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();


一个 ObjectAnimator 结合多个 PropertyValuesHolder 实现

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();


ViewPropertyAnimator: 只需一行代码


myView.animate().x(50f).y(100f);//myView.animate()直接返回一个 ViewPropertyAnimator 对象


2.2.7 PropertyValuesHolder
该类持有属性,相关属性值的操作以及属性的 setter,getter 方法的创建,属性值以 Keyframe 来承载,最c
其中核心类,
Property(自定义属性),
TypeEvaluate(估值器),
AnimatedValue(动画变化是的实时值,update监听器中返回的值),
/** 
 * 监听器一:监听动画变化时的实时值 
 */ 
public static interface AnimatorUpdateListener { 
    void onAnimationUpdate(ValueAnimator animation); 
}
void  calculateValue ( float fraction {
    mAnimatedValue  mKeyframeSet .getValue (fraction ) ;
}
 
时间点到了后,引发事件,自动设置dui'x属性值的变化函数:
void  setAnimatedValue ( Object target {
    if  ( mProperty  !=  null {
        mProperty .set (target getAnimatedValue ()) ;
    }
    if  ( mSetter  !=  null {
        try  {
            mTmpValueArray [ 0 getAnimatedValue () ;
            mSetter .invoke (target mTmpValueArray ) ;
        }  catch  ( InvocationTargetException e {
            Log .e ( "PropertyValuesHolder" e .toString ()) ;
        }  catch  ( IllegalAccessException e {
            Log .e ( "PropertyValuesHolder" e .toString ()) ;
        }
    }
}

此处自动更新属性值有2种情况,一种是对象的属性不能抛露给外部操作,或者是操作比较复杂,那么我们可以自定义一个属性,定义setter()和getter()方法,在setter()方法中完成对对象的复杂操作更新去自动完成,另一种是只需要指定对象存在的属性名,反射修改对象的属性


2.2.8 KeyFrame

KeyFrame 直译过来就是关键帧。 关键帧这个概念是从动画里学来的,我们知道视频里,一秒要播放 24 帧图片,对于制作 flash 动画的同学来讲,是不是每一帧都要画出来呢?当然不是了,如果每一帧都画出来,那估计做出来一个动画片都得要一年时间;比如我们要让一个球在 30 秒时间内,从(0,0)点运动到(300,200)点,那 flash 是怎么来做的呢,在 flash 中,我们只需要定义两个关键帧,在动画开始时定义一个,把球的位置放在(0,0)点;在 30 秒后,再定义一个关键帧,把球的位置放在(300,200)点。在动画 开始时,球初始在是(0,0)点,30 秒时间内就 adobe flash 就会自动填充,把球平滑移动到第二个关键帧的位置(300,200)点; 通过上面分析 flash 动画的制作原理,我们知道,一个关键帧必须包含两个原素,第一时间点,第二位置。即这个关键帧是表示的是某个物体在哪个时间点应该在哪个位置上。 

一个keyframe对象由一对 time / value 的键值对组成,可以为动画定义某一特定时间的特定状态。
每个keyframe可以拥有自己的插值器,用于控制前一帧和当前帧的时间间隔间内的动画。

Keyframe.ofFloat(0f,0f); 第一个参数为:要执行该帧动画的时间节点(elapsed time / duration)
第二个参数为属性值。
因此如果你想指定某一特定时间的特定状态,那么简单的使用 ObjectAnimator就满足不了你了,因为,ObjectAnimator.ofInt(....)类似的工厂方法,无法指定特定的时间点的状态。

每个 KeyFrame 的 Interpolator
每个KeyFrame其实也有个Interpolator。如果没有设置,默认是线性的。之前为Animator设置的Interpolator是整个动画的,而系统允许你为每一KeyFrame的单独定义Interpolator,系统这样做的目的是允许你在某一个keyFrame做特殊的处理,也就是整体上是按照你的插值函数来计算,但是,如果你希望某个或某些KeyFrame会有不同的动画表现,那么你可以为这个keyFrame设置Interpolator


因此,Keyframe 的定制性更高,你如果想精确控制某一个时间点的动画值及其运动规律,你可以自己创建特定的 Keyframe

Keyframe 使用
为了实例化一个keyframe对象,你必须使用某一个工厂方法:ofInt(), ofFloat(), or ofObject() 去获取合适的keyframe类型,然后你调用ofKeyframe工厂方法去获取一个PropertyValuesHolder对象,一旦你拥有了该对象,你可以将 PropertyValuesHolder 作为参数获取一个Animator,如下:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);//动画属性名,可变参数
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000);

2.2.9 KeyFrameSet

根据 Animator 传入的值,为当前动画创建一个特定类型的 KeyFrame 集合。
通常通过 ObjectAnimator.ofFloat(...)进行赋值时,这些值其实是通过一个 KeyFrameSet 来维护的
2.3 在 XML 中声明属性动画

通过在 XML 中定义的动画,可以很方便的在多个 Activities 中重用而且更容易编辑,复用性强。为了区分新的属性动画,从 3.1 开始,你应res/animator/下存放属性动画的资源文件,使用animator文件夹是可选的,但是如果你想在 Eclipse ADT 插件中使用布局编辑工具(ADT 11.0.0+),就必须在res/animator文件夹下存放了,因为 ADT 只会查找res/animator文件夹下的属性动画资源文件。

属性动画支持的 Tag 有
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>


AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.anim.property_animator);
set.setTarget(myObject);
set.start();


目录 res/animator/filename.xm

编译后的资源为
ValueAnimatorObjectAnimator, or AnimatorSet 

XML 文件的根元素必须为<set>,<objectAnimator>, or <valueAnimator>之一。也可以在一个 set 中组织不同的动画,包含其它<set>元素,也就是说,可以嵌套。

<set  
  android:ordering=["together" | "sequentially"]>  

    <objectAnimator  
        android:propertyName="string"  
        android:duration="int"  
        android:valueFrom="float | int | color"  
        android:valueTo="float | int | color"  
        android:startOffset="int"  
        android:repeatCount="int"  
        android:repeatMode=["repeat" | "reverse"]  
        android:valueType=["intType" | "floatType"]/>  

    <animator  
        android:duration="int"  
        android:valueFrom="float | int | color"  
        android:valueTo="float | int | color"  
        android:startOffset="int"  
        android:repeatCount="int"  
        android:repeatMode=["repeat" | "reverse"]  
        android:valueType=["intType" | "floatType"]/>  

    <set>  
        ...  
    </set>  
</set>


2.3.2 元素介绍
2.3.2.1 <set>

动画集合节点,有一个属性 ordering,表示它的子动画启动方式是先后有序的还是同时。

属性
sequentially:动画按照先后顺序
together (default) :动画同时启动

2.3.2.2 <objectAnimator>

一个对象的一个属性,相应的 Java 类为:ObjectAnimator

属性
android:propertyName:
String 类型,必须要设定的值,代表要执行动画的属性,通过名字引用,比如你可以指定了一个 View 的"alpha" 或者 "backgroundColor",这个 objectAnimator 元素没有暴露 target 属性,因此不能够在 XML 中执行一个动画,必须通过调用loadAnimator() 填充你的 XML 动画资源,并且调用setTarget() 应用到拥有这个属性的目标对象上。

android:valueTo
Float、int 或者 color,也是必须值,表明了动画结束的点,颜色由 6 位十六进制的数字表示。

android:valueFrom
相对应 valueTo,动画的起始点,如果没有指定,系统会通过属性身上的 get 方法获取,颜色也是 6 位十六进制的数字表示。

android:duration
动画的时长,int 类型,以毫秒为单位,默认为 300 毫秒。

android:startOffset
动画延迟的时间,从调用 start 方法后开始计算,int 型,毫秒为单位,

android:repeatCount
一个动画的重复次数,int 型,”-1“表示无限循环,”1“表示动画在第一次执行完成后重复执行一次,也就是两次,默认为 0,不重复执行。

android:repeatMode
重复模式:int 型,当一个动画执行完的时候应该如何处理。该值必须是正数或者是 -1,
“reverse”
会使得按照动画向相反的方向执行,可实现类似钟摆效果。
“repeat”
会使得动画每次都从头开始循环。

android:valueType
关键参数,如果该 value 是一个颜色,那么就不需要指定,因为动画框架会自动的处理颜色值。有 intType 和 floatType 两种:分别说明动画值为 int 和 float 型。

2.3.2.3 <animator>

在一个特定的时间里执行一个动画。相对应的是 ValueAnimator.所有的属性和一样 android:valueTo
android:valueFrom
android:duration
android:startOffset
android:repeatCount
android:repeatMode
android:valueType
Value Description
floatType (default)

res/animator/property_animator.xml:

<set android:ordering="sequentially">  
    <set>  
        <objectAnimator  
            android:propertyName="x"  
            android:duration="500"  
            android:valueTo="400"  
            android:valueType="intType"/>  
        <objectAnimator  
            android:propertyName="y"  
            android:duration="500"  
            android:valueTo="300"  
            android:valueType="intType"/>  
    </set>  
    <objectAnimator  
        android:propertyName="alpha"  
        android:duration="500"  
        android:valueTo="1f"/>  
</set>


为了执行该动画,必须在代码中将该动画资源文件填充为一个 AnimationSet 对象,然后在执行动画前,为目标对象设置所有的动画集合。
简便的方法就是通过 setTarget 方法为目标对象设置动画集合,代码如下:

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,  
   R.anim.property_animator);  
set.setTarget(myObject);  
set.start();



三 View anim 与 property anim 的比较
大家都知道逐帧动画主要是用来实现动画的,而补间动画才能实现控件的渐入渐出、移动、旋转和缩放的;而 Property Animator 是在 Android 3.0 版本才引入的,之前是没有的。大家可能会觉得补间动画和逐帧动画已经很全了,为什么还要引入 Property Animator 呢

1.实施目标对象不同:
a.view animation  提供的能力只能够为 View 添加动画。因此如果你想为非 View 对象添加动画,就必须自己去实现
b.property anim 完全弥补了 View anim System 的缺陷,你可以为一个对象的任何属性添加动画,(View 或者非 View)

2.目标本身属性是否修改:
a.传统动画是改变了 View 的绘制效果,真正的 View 的属性保持不变。 比如无论你在对话中如何缩放 Button 的大小,Button 的有效点击区域还是没有应用到动画时的区域,其位置与大小都不变
b.property anim, 同时对象自己会被修改, 并且当属性变化的时候,property Anim 系统会自动的刷新屏幕。比 如 Button 的缩放,Button 的位置与大小属性值都改变了,点击区域也改变。

3.可以实现更多复杂动画效果:
比如 View anim支持缩放和旋转,移动,透明度。
而属性动画,你可以指定动画的属性,或者自定义属性效果,比如颜色,位置,大小,定义动画的插值器并且同步多个动画。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值