Android 4.0 Animator框架

一、            前言

Animator框架是Android 4.0中新添加的一个动画框架,和之前的Animation框架相比,Animator可以进行更多和更精细化的动画控制,而且比之前更简单和更高效。在4.0源码中随处都可以看到Animator的使用。

 

二、            Animation和Animator比较

如下图,是Animation和Animator两个类继承图的对比。


Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是一个整个View动画,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU资源。

在Animator框架中使用最多的是AnimatorSet和ObjectAnimator配合,使用ObjectAnimator进行更精细化控制,只控制一个对象的一个属性值,多个ObjectAnimator组合到AnimatorSet形成一个动画。而且ObjectAnimator能够自动驱动,可以调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,而在不影响动画效果的前提下减少CPU资源消耗。

三、            关键接口介绍

1.      ObjectAnimator介绍

Animator框架封装得比较完美,对外提供的接口非常简单,创建一个ObjectAnimator只需通过如下图所示的静态工厂类直接返回一个ObjectAnimator对象。传的参数包括一个对象和对象的属性名字,但这个属性必须有get和set函数,内部会通过java反射机制来调用set函数修改对象属性值。还包括属性的初始值,最终值,还可以调用setInterpolator设置曲线函数。

2.      AnimatorSet介绍

AnimatorSet主要是组合多个AnimatorSet和ObjectAnimator形成一个动画,并可以控制动画的播放顺序,其中还有个辅助类通过调用play函数获得。

3.   AnimatorUpdateListner介绍

通过实现AnimatorUpdateListner,来获得属性值发生变化时的事件,在这个回调中发起重绘屏幕事件。

 

四、            使用实例

在Android4.0中的ApiDemo中有个BouncingBalls实例,描述了Animator框架的使用,当点击屏幕时,绘制一个球从点击位置掉到屏幕底部,碰到底部时球有压扁的效果,然后回弹到点击位置再消失。

代码如下:

ShapeHolder newBall =addBall(event.getX(), event.getY());

 

           // Bouncing animation with squash and stretch

           float startY = newBall.getY();

           float endY = getHeight() - 50f;

           float h = (float)getHeight();

           float eventY = event.getY();

           int duration = (int)(500 * ((h - eventY)/h));

           ValueAnimator bounceAnim = ObjectAnimator.ofFloat(newBall, "y", startY, endY);

           bounceAnim.setDuration(duration);

           bounceAnim.setInterpolator(new AccelerateInterpolator());

           ValueAnimator squashAnim1 = ObjectAnimator.ofFloat(newBall, "x", newBall.getX(),

                    newBall.getX() - 25f);

           squashAnim1.setDuration(duration/4);

           squashAnim1.setRepeatCount(1);

           squashAnim1.setRepeatMode(ValueAnimator.REVERSE);

            squashAnim1.setInterpolator(new DecelerateInterpolator());

           ValueAnimator squashAnim2 = ObjectAnimator.ofFloat(newBall, "width", newBall.getWidth(),

                    newBall.getWidth() + 50);

           squashAnim2.setDuration(duration/4);

           squashAnim2.setRepeatCount(1);

           squashAnim2.setRepeatMode(ValueAnimator.REVERSE);

           squashAnim2.setInterpolator(new DecelerateInterpolator());

           ValueAnimator stretchAnim1 = ObjectAnimator.ofFloat(newBall, "y", endY,

                    endY + 25f);

           stretchAnim1.setDuration(duration/4);

           stretchAnim1.setRepeatCount(1);

           stretchAnim1.setInterpolator(new DecelerateInterpolator());

           stretchAnim1.setRepeatMode(ValueAnimator.REVERSE);

           ValueAnimator stretchAnim2 = ObjectAnimator.ofFloat(newBall, "height",

                    newBall.getHeight(),newBall.getHeight() - 25);

           stretchAnim2.setDuration(duration/4);

           stretchAnim2.setRepeatCount(1);

           stretchAnim2.setInterpolator(new DecelerateInterpolator());

           stretchAnim2.setRepeatMode(ValueAnimator.REVERSE);

           ValueAnimator bounceBackAnim = ObjectAnimator.ofFloat(newBall, "y", endY,

                    startY);

            bounceBackAnim.setDuration(duration);

           bounceBackAnim.setInterpolator(newDecelerateInterpolator());

           // Sequence the down/squash&stretch/upanimations

           AnimatorSet bouncer = new AnimatorSet();

           bouncer.play(bounceAnim).before(squashAnim1);

           bouncer.play(squashAnim1).with(squashAnim2);

           bouncer.play(squashAnim1).with(stretchAnim1);

           bouncer.play(squashAnim1).with(stretchAnim2);

           bouncer.play(bounceBackAnim).after(stretchAnim2);

 

           // Fading animation - remove the ball when theanimation is done

           ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);

           fadeAnim.setDuration(250);

           fadeAnim.addListener(new AnimatorListenerAdapter() {

               @Override

               public void onAnimationEnd(Animatoranimation) {

                    balls.remove(((ObjectAnimator)animation).getTarget());

 

               }

           });

           // Sequence the two animations to play oneafter the other

           AnimatorSet animatorSet = new AnimatorSet();

           animatorSet.play(bouncer).before(fadeAnim);

 

           // Start the animation

           animatorSet.start();

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值