Android动画之Property Animation(一)

Android3.0以后加入了一种新的动画机制Property Animation(属性动画),单从名字来讲,这种动画方式的主要用途是用来动态改变view的属性值,从而达到动画的效果。


对于Property Animation, 我们需要为它指定下述几个属性才能描述这个动画的效果:

  1. Duration:动画的持续时间
  2. Repeat count and behavior:动画要被重复执行的次数和行为,如想要动画从反方向播放等。
  3. Frame refresh delay: 动画采样间隔,多长时间刷新一次,系统默认为10ms
  4. Time interpolation:时间插值器,非常重要,它对动画已执行过的时间(这里的时间,通常用动画完成的百分比表示)进行重新计算。假如,动画持续10s,属性值从0f变化到1f,那么每秒的变化增量为0.1f, 这里假设动画采样间隔为1s,采样出来的属性序列为:0f->0.1f->0.2f->0.3f->...->0.9f->1f,如果我们不用线性插值器,而用加速插值器,那么,需要对上面的序列重新计算,属性序列可能会变为:0f->0.05->0.11->...->0.8f->1f,属性的变化率会越来越大,如前面两帧变化率为0.05f-0f=0.05f, 最后面两帧变化率则为1f-0.8f = 0.2f,将这个值应用到改变物体的位置时,就会感觉物体移动越来越快,这就是加速的效果。
  5. Animator sets:可以指定一组动画,并且对它们可以制定自己的播放时序。
只有真正理解了什么是时间插值器,才能真正了解动画原理,Android API文档里面的这个图有助于对Time interpolation的理解(图一)

上面使用的是线性插值,Frame refresh delay = 10ms, duration = 40 ms, 属性x变化范围为x=0 -> x=40, 每10ms,x的变化为10

如果用加先加速再减速插值的话,会变成下面的状态(图二),

第一帧和第二帧的变化率为6,二三帧变化率为14,这段时间为加速状态
第三帧和第四帧变化率为14,四五帧变化率为6,这段时间为减速状态。
实际上为了运算方便,android将这种增量换算成动画完成率fraction,比如图二,第一帧fraction=0.0,第二帧fraction=6/40,第三帧fraction=20/40,最后一帧40/40=1;

从上面的介绍可以知道,Property Animation的核心是如何计算每个时间点的动画完成率,只有知道这个完成率就可以计算出这个时间点实际的属性值。这个任务是由一个叫ValueAnimator的类负责完成,单看类名,它是对Value进行动画模拟的,所以,它并不会真正产生动画,需要我们实现onAnimationUpdate()接口,并绑定到ValueAnimator上。

ValueAnimator对象的创建需要指明计算增量的TimeInterpolator(如果没有指定,默认是线性插值方法),TypeEvaluato用来指定在知道fraction和属性变化范围,如何计算实际上的属性值是多少,它有IntEvaluator, FloatEvaluator等,另外就是指明属性的变化范围。

AccelerateDecelerateInterpolator是TimeInterpolator的子类,它提供了方法
public float getInterpolation (float fraction)
来计算插值,fraction是0.0f到0.1f之间的数,表示在没有插值时某个时间点的动画完成率(因为没有插值相当于线性插值,匀速变化,所以也相当于线性插值下动画的完成率),图一第二帧经过加减速插值计算后会变成图二第二帧的状态,也就是fraction由10/40=0.25变为6/40=0.15

当计算出fraction后再由TypeEvaluator得到当前动画完成率下属性的值。假如用 用IntEvaluator来计算,它提供下面的方法
public Integer evaluate (float fraction, Integer startValue, Integer endValue)
其中fraction表示当前动画的完成率(注意:是经过插值后的完成率),startValue和endValue表示属性变化范围,返回值为当前动画状态下的属性值,它的计算方法为 startValue + fraction * ( endValue - startValue )
如果使用ofInt()构建的ValueAnimator,系统会自动调用IntEvaluator的evaluate()方法计算变化后的属性值,同样,ofFloat()对应了FloatEvaluator。假设我们使用了系统不认识的属性类型,那么就需要手动实现TypeEvaluator,用法如下

// 自定义属性 
private class MyProperty {
        float p1;
        float p2;

        public MyProperty(float p1, float p2) {
            this.p1 = p1;
            this.p2 = p2;
        }
    }

    // 自定义TypeEvaluator
    private class MyTypeEvaluator implements TypeEvaluator<MyProperty> {

        /*
         * (non-Javadoc)
         * @see android.animation.TypeEvaluator#evaluate(float,
         * java.lang.Object, java.lang.Object)
         */
        @Override
        public MyProperty evaluate(float fraction, MyProperty p1, MyProperty p2) {
            // TODO Auto-generated method stub
            // 定义自己的计算方法, 这里随便写了
            float p_1 = p1.p1 + fraction * p2.p2;
            float p_2 = p1.p1 + fraction * p2.p2;
            MyProperty myProperty = new MyProperty(p_1, p_2);
            return myProperty;
        }
    }

接下来构造属性为Object类型的ValueAnimator,并指定自定义的TypeEvaluator
   // 使用自己的TypeEvaluator
   ValueAnimator animator = ValueAnimator.ofObject(new MyTypeEvaluator(), new MyProperty(1.0f, 2.0f), new MyProperty(3.0f,4.0f));
   animator.addUpdateListener(new MyUpdateListener());
   animator.start();
最后重写 onAnimationUpdate(),对属性进行相应的操作
private class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {

        @Override
        public void onAnimationUpdate(ValueAnimator animator) {
            // TODO Auto-generated method 
            MyProperty value2 = (MyProperty)animator.getAnimatedValue();
            float p_1 = value2.p1;
            float p_2 = value2.p2;
        }
    }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值