Android 动画学习(二)之Property Animation初步介绍

转载请注明出处:http://blog.csdn.net/yegongheng/article/details/38397725

  

        上一篇文章我们简单了解了Android Animation的分类和每一种Animation系统的特点,并详细介绍了View Animation的相关知识点,通过具体实例加深了对View Animation的理解和实际应用。那本篇文章将继续向读者介绍功能更为强大、灵活的动画系统--Property Animation。

Property Animation 初步

       Property Animation 是Android3.0(level 11)引入的一个款功能强大、灵活、健壮的动画系统,它可以为任何包括View在内的对象添加动画效果。就实现原理来分析,Property Aniamtion和Tween Animation之间最大的区别就是前者在为对象添加动画效果时,其更改的是对象的实际属性,而后者改变的只是View的绘制效果,View的实际属性值是不发生改变的。比如对一个Button实现左右移动的动画,若使用Property Animation实现的话,Button在移动的过程中,由于Property Animation改变的是Button的实际属性值,因此Button的事件响应焦点也随着移动,若点击移动中的Button,其可响应事件点击;而使用View Animation实现的话,点击移动中的Button,则无法响应事件点击,原因是Button控件本身的实际位置依然在初始位置,其事件响应焦点也依然在初始位置。

       Property Animation功能强大,使用起来也非常的灵活,一般的,要实现一个Property Animation的动画,动画系统允许你设置一下动画的元素信息:

      (1) 持续时间:指定动画的持续显示时间。默认的时长是300毫秒。
      (2) 图像插值方式:指定属性值的变化方式,表示为关于动画已显示时间的函数。
      (3) 重复次数和方式:指定动画是否循环播放,以及重复的次数。还可以指定动画是否反向播放。可以设为先正向播放再反向回放,如此往复直至达到设定的重复次数。
      (4) 动画集合:你可以把动画分为多个逻辑组,以便实现同时播放、顺序播放或间隔一段时间再播放。
      (5) 帧刷新间隔:指定动画帧的刷新频率。默认是每 10 ms刷新一次,但应用程序实际可执行的刷新频率取决于系统整体的繁忙程度,以及系统对定时器的支持程度。

Property Animation的工作方式

    在学习Property Animation的工作之前,我们先通过一张图来看一下使用Property Animation的来实现动画的主要类及其相互之间的工作方式,如图下:



ValueAnimator:该类作为Property Animation系统的主要核心类,它记录了动画自身的一些属性值,比如动画显示的时间,动画对应当前属性的起始值和结束值。同时,ValueAnimator封装了一个计算插值因子的TimeInterpolator以及定义属性计算方式的TypeEvaluator。我们要实现一个Property Animation,都需要使用ValueAnimator或ValueAnimator的子类(ObjectAnimator)来完成动画的配置信息和计算过程。那ValueAnimator及其子类到底是如何完成动画的配置信息和计算过程的呢?下面我将会一一详细地分析,从而使读者了解Property Animation的工作方式:

       要启动动画,首先创建一个 ValueAnimator或其子类并指定要动画显示的属性的初始值、结束值以及显示时间,然后调用 start() 启动动画。在整个动画过程中, ValueAnimator 根据动画总时间和已进行的时间自动计算出一个时间比例因子(elapsed fraction),大小介于0和1之间。 时间比例因子代表动画已完成时间的百分比,0 表示 0%,1 表示 100%。ValueAnimator 算完时间比例因子后,将调用已设置好的 TimeInterpolator 计算出一个插值因子(interpolated fraction)。插值因子是一个由时间比例因子换算出来的图像显示状态因子。算完插值因子, ValueAnimator 就会调用合适的 TypeEvaluator ,根据插值因子、初始值、结束值计算出需要动画显示的属性值。计算出属性值后,最后为需要执行动画的对象设置对应属性的属性值。动画在持续的整个过程中,会根据我们当初设置的TimeInterpolator 和TypeEvaluator的计算方式计算出的不同的属性值,从而不断地改变对象属性值的大小,进而产生各式各样的动画效果。

       上面讲解Property Animation的动画执行过程可能会比较抽象,下面我们将通过一张图和一个实例来更形象地阐述一下Property Animation的属性计算方式和工作流程。Property Animation的工作流程一般分为四个步骤,如下图:


下面我们接着使用一个例子来了解一下一个对象执行Property Aniamtion的属性计算方式过程。下图(图一)是一个对象的x属性值的变化情况,即在屏幕上的水平位置。该对象从0到40像素点的移动变化过程总共持续了40ms的时间,并以每10ms的帧刷新频率来刷新一次对象,观察下图,每隔10ms,对象所移动的距离都是10个像素点,很明显我们能得出结论该对象的动画是匀速移动的。


                                               图 1

在Android中,我们称以上为以线性插值的方式执行动画,那默认设置的计算插值因子的TimeInterpolator为LinearInterpolator,计算属性的TypeEvaluator为IntEvaluator。这两个类均由系统提供,我们分别看一下两个类的源码,首先是LinearInterpolator的源码如下:

[java]  view plain copy
  1. package android.view.animation;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5.   
  6. /** 
  7.  * An interpolator where the rate of change is constant 
  8.  * 
  9.  */  
  10. public class LinearInterpolator implements Interpolator {  
  11.   
  12.     public LinearInterpolator() {  
  13.     }  
  14.       
  15.     public LinearInterpolator(Context context, AttributeSet attrs) {  
  16.     }  
  17.       
  18.     public float getInterpolation(float input) {  
  19.         return input;  
  20.     }  
  21. }  

LinearInterpolator类中的实现比较简单,除了构造方法外,就只有一个getInterpolation(float input)方法,该方法用于计算插值因子,参数input为时间比例因子,我们发现以匀速线性插值方式执行的动画的时间比例因子和插值因子是等值的。那有读者会问,时间比例因子又是怎么得来的呢,很简单,记住这个公式就行:时间比例因子 = 动画执行的总时间/当前已进行的时间。

IntEvaluator的源码如下:

[java]  view plain copy
  1. package android.animation;  
  2.   
  3. /** 
  4.  * This evaluator can be used to perform type interpolation between <code>int</code> values. 
  5.  */  
  6. public class IntEvaluator implements TypeEvaluator<Integer> {  
  7.   
  8.     public Integer evaluate(float fraction, Integer startValue, Integer endValue) {  
  9.         int startInt = startValue;  
  10.         return (int)(startInt + fraction * (endValue - startInt));  
  11.     }  
  12. }  
IntEvaluator类的实现也比较简单,只有一个evaluate(float fraction, Integer startValue, Integer endValue)方法用于计算当前的属性值,其中参数fraction为插值因子,startValue和endValue为属性的起始值和属性的结束值。

分析LinearInterpolator和IntEvaluator后,我们来做一个实验,就是借助LinearInterpolator和IntEvaluator类自己来计算一下上面实例的属性值的变化,具体代码如下:

[java]  view plain copy
  1. public class LinearTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         // TODO Auto-generated method stub  
  5.         //当前的时间  
  6.         float time = 10;  
  7.         //时间比例因子  
  8.         float timeFactor = 0.0f;  
  9.         for(int i = 0;i < 4;i++){  
  10.             System.out.println("时间 = " + time +"ms");  
  11.             timeFactor = time/40;  
  12.             System.out.println("时间因子 = "+ timeFactor);  
  13.             //插值因子  
  14.             float interpolatorFactor = LinearTest.getInterpolation(timeFactor);  
  15.             System.out.println("插值因子 = " + interpolatorFactor);  
  16.             //属性值  
  17.             int propertyValue = evaluate(interpolatorFactor, 040);  
  18.             System.out.println("属性值 = " + propertyValue);  
  19.             time += 10;  
  20.             System.out.println();  
  21.         }  
  22.           
  23.     }  
  24.       
  25.     /** 
  26.      * 计算插值因子 
  27.      * @param input 时间比例因子 
  28.      * @return float 返回插值因子 
  29.      */  
  30.      public static float getInterpolation(float input) {  
  31.             return input;  
  32.      }  
  33.       
  34.      /** 
  35.       * 计算当前的属性值 
  36.       * @param fraction 插值因子 
  37.       * @param startValue 属性起始值 
  38.       * @param endValue 属性结束值 
  39.       * @return Integer 当前的属性值 
  40.       */  
  41.      public static Integer evaluate(float fraction, Integer startValue, Integer endValue) {  
  42.             int startInt = startValue;  
  43.             return (int)(startInt + fraction * (endValue - startInt));  
  44.      }  
  45.       
  46. }  
运行程序,打印的结果如下:

[plain]  view plain copy
  1. 时间 = 10.0ms  
  2. 时间因子 = 0.25  
  3. 插值因子 = 0.25  
  4. 属性值 = 10  
  5.   
  6. 时间 = 20.0ms  
  7. 时间因子 = 0.5  
  8. 插值因子 = 0.5  
  9. 属性值 = 20  
  10.   
  11. 时间 = 30.0ms  
  12. 时间因子 = 0.75  
  13. 插值因子 = 0.75  
  14. 属性值 = 30  
  15.   
  16. 时间 = 40.0ms  
  17. 时间因子 = 1.0  
  18. 插值因子 = 1.0  
  19. 属性值 = 40  
查看实验结果,我们发现执行的结果与我们预想一致。

       我们再来看看下图(图2),如同上一张图一样,对象的x属性值都是从0到40像素的变化过程,总共持续时间也都是40ms,帧刷新频率都是10ms每次。唯一不同的就是在相同间隔的时间里对象所移动的距离各不相同,如下图中对象在前10ms所移动的距离为6个像素点,而在第10至20ms这个时间段对象所移动的距离为14个像素点,还有在第20至30ms和第30至40ms之间该对象所移动的距离又分别是14和6个像素点。依此我们可以发现,该对象是以先加速后减速的方式进行非匀速运动的。


                                                                            图2

 那在Android中,我们称以上为以非线性插值的方式执行动画。那默认设置的计算插值因子的TimeInterpolator为AccelerateDecelerateInterpolator,计算属性的TypeEvaluator为FloatEvaluator。这两个类均由系统提供,我们分别看一下两个类的源码,首先是AccelerateDecelerateInterpolator的源码如下:

[java]  view plain copy
  1. package android.view.animation;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5.   
  6. /** 
  7.  * An interpolator where the rate of change starts and ends slowly but 
  8.  * accelerates through the middle. 
  9.  *  
  10.  */  
  11. public class AccelerateDecelerateInterpolator implements Interpolator {  
  12.     public AccelerateDecelerateInterpolator() {  
  13.     }  
  14.       
  15.     @SuppressWarnings({"UnusedDeclaration"})  
  16.     public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {  
  17.     }  
  18.       
  19.     public float getInterpolation(float input) {  
  20.         return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;  
  21.     }  
  22. }  
FloatEvaluator的源代码,如下:

[java]  view plain copy
  1. package android.animation;  
  2.   
  3. /** 
  4.  * This evaluator can be used to perform type interpolation between <code>float</code> values. 
  5.  */  
  6. public class FloatEvaluator implements TypeEvaluator<Number> {  
  7.   
  8.     public Float evaluate(float fraction, Number startValue, Number endValue) {  
  9.         float startFloat = startValue.floatValue();  
  10.         return startFloat + fraction * (endValue.floatValue() - startFloat);  
  11.     }  
  12. }  
AccelerateDecelerateInterpolator类和FloatEvaluator中的方法在这里就不多介绍了,它们和前面所讲的LinearInterpolator和IntEvaluator类似。那我们同样做这样一个测试实验,具体的源代码如下:

[java]  view plain copy
  1. public class AccelerateDecelerateTest {  
  2.   
  3.     public static void main(String[] args) {  
  4.         // TODO Auto-generated method stub  
  5.         //当前的时间  
  6.         float time = 10;  
  7.         //时间比例因子  
  8.         float timeFactor = 0.0f;  
  9.         for(int i = 0;i < 4;i++){  
  10.             System.out.println("时间 = " + time +"ms");  
  11.             timeFactor = time/40;  
  12.             System.out.println("时间因子 = "+ timeFactor);  
  13.             //插值因子  
  14.             float interpolatorFactor = AccelerateDecelerateTest.getInterpolation(timeFactor);  
  15.             System.out.println("插值因子 = " + interpolatorFactor);  
  16.             //属性值  
  17.             float propertyValue = evaluate(interpolatorFactor, 040);  
  18.             System.out.println("属性值 = " + propertyValue);  
  19.             time += 10;  
  20.             System.out.println();  
  21.         }  
  22.           
  23.     }  
  24.       
  25.     /** 
  26.      * 计算插值因子 
  27.      * @param input 时间比例因子 
  28.      * @return float 返回插值因子 
  29.      */  
  30.     public static float getInterpolation(float input) {  
  31.         return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;  
  32.     }  
  33.       
  34.     /** 
  35.       * 计算当前的属性值 
  36.       * @param fraction 插值因子 
  37.       * @param startValue 属性起始值 
  38.       * @param endValue 属性结束值 
  39.       * @return Integer 当前的属性值 
  40.       */  
  41.     public static Float evaluate(float fraction, Number startValue, Number endValue) {  
  42.         float startFloat = startValue.floatValue();  
  43.         return startFloat + fraction * (endValue.floatValue() - startFloat);  
  44.     }  
  45.       
  46. }  
运行程序, 打印的结果如下:
[plain]  view plain copy
  1. 时间 = 10.0ms  
  2. 时间因子 = 0.25  
  3. 插值因子 = 0.14644662  
  4. 属性值 = 5.8578644  
  5.   
  6. 时间 = 20.0ms  
  7. 时间因子 = 0.5  
  8. 插值因子 = 0.5  
  9. 属性值 = 20.0  
  10.   
  11. 时间 = 30.0ms  
  12. 时间因子 = 0.75  
  13. 插值因子 = 0.8535534  
  14. 属性值 = 34.142136  
  15.   
  16. 时间 = 40.0ms  
  17. 时间因子 = 1.0  
  18. 插值因子 = 1.0  
  19. 属性值 = 40.0  

观察运行结果,与我们预期的结果基本一致。

      小结:至此,我们通过流程图和实例的分析加深了对Property Animation的属性计算方式和如何实现动画的工作方式的理解。下一篇博文我们将学习如何使用Property Animation系统提供的API实现一些比较炫的动画,敬请期待!


源代码下载,请戳下载:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值