Andorid Animation and Graphics系列(二)

来源:互联网 发布:设计手机主题软件 编辑:程序博客网 时间:2024/05/16 16:37

属性动画Property Animation

Property Animation区别于View Animation,主要有以下几点:

  • Property Animation的动画对象是Object,而View Animation只适用于View及其子类
  • Property Animation真正的改变了对象的属性,而View Animation只是改变了View在屏幕上所画的位置。比如,用View Animation让一个按钮移动并停留在移动后的位置,他的点击事件竟然还保留在他原来的位置!

Property Animation主要的类及其说明

Class Description ValueAnimator Property Animation的主要计时引擎也会计算要达到的属性值。他具有所有的核心功能包括计算动画属性值和动画的计时详情,一个动画重复、接收动画事件更新的监听器和设置自定义计算类型的能力。在属性动画执行的时候需要注意两点:一是计算动画的属性值,二是把这些值设置到要被执行动画的对象中去。ValueAnimation不会完成第二条,所以我们必须监听由ValueAnimation计算出来的按照我们自己逻辑的动画数值。 ObjectAnimator ValueAnimator的子类,允许给动画设置目标对象和目标属性。当ObjectAnimator计算出一个新的动画属性值,他会做相应的更新。我们大多数在写属性动画的时候都会使用ObjectAnimator,因为他使得目标对象的动画属性值变化过程更易观察。然而由于一些限制性因素,有时候我们也需要使用另外一种ValueAnimator。 AnimatorSet 提供了一种组织多个动画在一起的机制以使他们能够关联地执行。我们可以使他们顺序的执行,也可以间隔一个延迟时间去执行。

Property Animation主要的属性计算器类及其说明

Class/Interface Description IntEvaluator 默认结算int类型属性值的计算器 FloatEvaluator 默认结算Float类型属性值的计算器 ArgbEvaluator 默认结算颜色数值的十六进制类型属性值的计算器 TypeEvaluator 一个可以允许自己实现属性计算器的接口,如果我们定义的动画对象属性的值既不是int,也不是float,也不是颜色,那么我们需要实现这个接口来自己定义怎么计算对象属性的动画值。另外如果我们想让对象属性动画值的处理和默认的前三种计算机不一样,也可以自定义前三种类型的计算器。

Property Animation主要的动画插入器类及其说明

Interpolator译为插入器有点僵硬,他的意思是在动画执行过程中动画对象变化的速率,因为执行过程中Interpolator不断的改变速率,就好像不断的干涉到其中,所以形象的称这个对象为插入器Interpolator。

Class/Interface Description AccelerateDecelerateInterpolator 前半段加速,后半段减速,中间位置达到速率的最大值 AccelerateInterpolator 起始阶段由慢变快加速,结束位置达到速度的最大值 AnticipateInterpolator 先向后,再向前投射 AnticipateOvershootInterpolator 先向后,再向前投射越过动画最终的值,最后还返回到最终值的位置 BounceInterpolator 最后阶段弹跳效果 CycleInterpolator 动画效果会循环特定的次数 DecelerateInterpolator 速率递减 LinearInterpolator 速率恒定为常量值 OvershootInterpolator 向前投射越过上一个值,最终返回规定的动画结束值的位置 TimeInterpolator 一个允许实现自定义Interpolator的接口

好啦,上面列述了那么多枯燥的内容,下面就开始有趣的实践吧!

Property Animation代码示例

ValueAnimator

ValueAnimator类可以让我们通过设定一系列的int、float或者color值来达到实现动画的目的。可以通过ValueAnimator的工厂类方法如ofInt()、ofFloat()或者ofObject来获取ValueAnimator。

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);animation.setDuration(1000);animation.start();

这段代码里,当start()方法执行时,ValueAnimator开始计算0到1之间的动画值。
也可以像下边这样定义一个自定义类型的动画。

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);animation.setDuration(1000);animation.start();

上面这段代码的意思是,start()方法运行后接下来的1000毫秒内,ValueAnimator将按照MyTypeEvaluator类里的逻辑在startPropertyValue和endPropertyValue之间计算动画的值。

然而,上述的两段代码并没有对动画对象产生什么影响,因为他没有直接操作动画对象的属性值,而只是计算出了在规定区间的变化值,没有赋给相应的属性。要想达到想要的效果,当ValueAnimator计算值的时候需要我们自己来处理动画对象属性值的更新,而另外一个类ObjectAnimator继承自ValueAnimator,将时间引擎、ValueAnimator计算出的值和目标对象的某一属性名连接了起来,这使得我们不用再去实现ValueAnimator.AnimatorUpdateListener接口,ObjectAnimator已经帮我们做了这件事。

ObjectAnimator

ObjectAnimator获取方法和ValueAnimator相似,参数略有不同。

ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);anim.setDuration(1000);anim.start();

这段代码会改变foo对象的alpha属性,变化范围从0f到1f持续1000毫秒。
为了能达到动画效果,ObjectAnimator对动画对象有几点要求:

1.要应用的动画属性必须在动画对象中又set<属性名>()这个set方法,因为在动画持续的时间内,ObjectAnimator需要不断地去改变动画对象的这个属性值,就是通过调用动画对象的set<属性名>()这个方法。比如想改变属性A的值,那这个方法就是setA()。如果动画对象没有这个方法,那么有三种解决办法:

 ①如果有权限的话将这个set方法加入到这个动画对象中 ②如果有权限改变动画属性值的话,使用一个包装类接收计算出来的属性值赋给被包装类(动画对象)的相应属性 ③用ValueAnimator替代ObjectAnimator,自己实现相应逻辑 

2.细心的我们会发现,ObjectAnimator的几个工厂方法中所要求的value…参数是个可变长参数。如果我们只传了一个值,这个值就会被当做动画对象属性的最终值,所以动画对象必须有一个get方法来获取动画对象属性的初始值,同样的这个get方法的格式必须是get<属性名>()。

3.要操作的动画对象的get和set方法所操作的数据类型必须和我们引用的工厂方法中的数据类型相同,即ObjectAnimator.ofInt()对应的是setXXX(int)和getXXX(int)。

4.有的情况下,根据动画对象或者其属性的不同,在动画属性值发生改变的时候可能需要调用View的invalidate()方法来重绘这个对象。这个过程在onAnimationUpdate()中来做。比如,Drawable对象的颜色属性只有在重绘自己的时候才会改变。View对象的所有set方法,比如setAlpha()和setTranslationX()都会刷新界面,所以传递新值调用这些方法的时候就没有必要再去调用invalidate()方法了。

AnimatorSet组织多个动画

很多情况下,我们想要在另一个动画开始或者结束的时候开启一个动画。Android系统支持将一系列动画绑定在一起放在AnimatorSet中,这样我们可以决定这些动画是否同时、顺序、或者在特定的一段时间后执行。多个AnimatorSet也可以互相嵌套。

下面这段代码是一个简单的例子

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);ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);fadeAnim.setDuration(250);AnimatorSet animatorSet = new AnimatorSet();animatorSet.play(bouncer).before(fadeAnim);animatorSet.start();
0 0