Android中的Animation分三种:
1. View Animation
2. Property Animation
3. Drawable Animation

下面我们详细介绍几种Animation

1.Property Animation

3.0之前已有的动画框架View Animation存在一些局限性,Animation框架定义了透明度,旋转,缩放和位移几种常见的动画,而且控制的是整个View,实现原理是每次绘制视图时View所在的ViewGroup中的drawChild函数获取该View的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧,如果动画没有完成,继续调用invalidate()函数,启动下次绘制来驱动动画,动画过程中的帧之间间隙时间是绘制函数所消耗的时间,可能会导致动画消耗比较多的CPU资源,最重要的是,动画改变的只是显示,并不能相应事件。比如:你希望View有一个颜色的切换动画;你希望可以使用3D旋转动画;你希望当动画停止时,View的位置就是当前的位置;这些View Animation都无法做到。这就是Property Animation(Android 3.0版本)产生的原因。

1.1相关API

Property Animation故名思议就是通过动画的方式改变对象的属性了,我们首先需要了解几个属性:
Duration动画的持续时间,默认300ms。
Time interpolation:时间差值,乍一看不知道是什么,但是我说LinearInterpolator、AccelerateDecelerateInterpolator,大家一定知道是干嘛的了,定义动画的变化率。
Repeat count and behavior:重复次数、以及重复模式;可以定义重复多少次;重复时从头开始,还是反向。
Animator sets: 动画集合,你可以定义一组动画,一起执行或者顺序执行。
Frame refresh delay:帧刷新延迟,对于你的动画,多久刷新一次帧;默认为10ms,但最终依赖系统的当前状态;基本不用管。

相关的类
AnimatorInflater 用户加载属性动画的xml文件
TimeInterpolator 定义了动画的时间插值,比如可以线性或者加速减速
Animator:它提供了创建animation最基本的结构,基本上不会直接地用到这个类,要使用这个类,必须继承它并实现需要的功能。
ValueAnimator:property animation主要的时间引擎,它计算了各个帧的属性值。它包括所有核心功能:计算每个帧的相关内容,负责接收更新事件,按属性值的类型自定义计算规则。一个动画需要完成两大块内容:计算各帧的相关内容和并为对象设置这些计算后的值。ValueAnimator不负责第二块内容,因此你必须由ValueAnimator监听计算值的更新并修改对象相关属性值。
ObjectAnimator:ValueAnimator子类,它允许你设置一个对象的属性来完成动画。ObjectAnimator更加常用,因为使用它来建立动画会更加简单。然而,有时你需要用到ValueAnimator,因为ObjectAnimator会有一些限制。
AnimatorSet:把多个Animator捆绑在一起,可以让他们同时播放,或按顺序地播放、或延时一段时间播放。
Evaluators:Property Animation系统如何去计算属性值。Property Animation系统提供了下面的一些Evaluator:

  1. IntEvaluator:用于计算Int类型属性值的计算器。
  2. FloatEvaluator:用于计算Float类型属性值的计算器。
  3. ArgbEvaluator:用于计算以16进制形式表示的颜色值的计算器。
  4. TypeEvaluator:一个计算器接口,它允许你创建你自己的计算器。如果你正在计算一个对象属性并不是int,float或者颜色值类型的,那么你必须实现TypeEvaluator接口去指定如何去计算对象的属性值。

在android.view.animation包中定义的TimeInterpolator:

  1. AccelerateDecelerateInterpolator:先加速后减速的插值器
  2. AccelerateInterpolator:加速插值器
  3. AnticipateInterpolator:先往变化的相反方向回退,然后甩到尾值的插值器
  4. AnticipateOvershootInterpolator:先往变化的相反方向回退,然后甩到尾值并越过尾值,再返回到尾值。
  5. BounceInterpolator:
  6. CycleInterpolator:指定重复次数的插值器
  7. DecelerateInterpolator:减速插值器
  8. LinearInterpolator:线性(匀速)插值器
  9. OvershootInterpolator:超过尾值再返回到尾值的插值器
  10. TimeInterpolator:用于实现自己的插值器的接口

例如示例2(下面提到的例2)中,TimeInterpolator使用的是AccelerateDecelerateInterpolator,TypeEvaluator使用的是IntEvaluator
Android:Property Animation_第1张图片

更多的类介绍 http://blog.csdn.net/sin90lzc/article/details/7517837

总的来说,属性动画就是,动画的执行类来设置动画操作的对象的属性、持续时间,开始和结束的属性值,时间差值等,然后系统会根据设置的参数动态的变化对象的属性

1.2动画创建过程

这里我们先举两个例子
例子1:(Linear Animation):Animation要求一个物体A的x属性在40ms内匀速地从0px变化到40px。帧的刷新率默认为10ms/帧。
Android:Property Animation_第2张图片
例子2:(Not-Linear Animation):Animation要求一个物体A的x属性在40ms内先加速后减速地从0px变化到40px。帧的刷新率默认为10ms/帧。

为了开启一个动画,首先构造一个ValueAnimator对象,把你想要改变的属性值的起始值、终止值以及动画时间告诉它,当你调用 start()方法时,动画开始。
在整个动画的过程中,所涉及的计算分为下面三步:
1.这个ValueAnimator对象会根据动画的总时间和已经流逝的时间计算出一个0到1之间的elapsed fraction值。这个elapsed fraction值就代表了时间完成的程度。
2.计算出elapsed fraction之后,ValueAnimator对象会调用TimeInterpolator 来计算一个interpolated fraction,即,根据所设置的时间插值方法将elapsed fraction映射到interpolated fraction。
如果是线性插值的话elapsed fraction和interpolated fraction会是一直相等的,但是非线性变换就不是了。
3. interpolated fraction计算出来后,ValueAnimator 会调用TypeEvaluator,来进行你要动画的属性值的计算。
这时候用的输入参数就是interpolated fraction的值,以及属性值的起始值和终止值。

如上例中10ms时:
1.首先计算出时间因子(elapsed fraction),即经过的时间百分比:t=10ms/40ms=0.25
2.经插值计算(inteplator)后的插值因子(interpolated fraction):大约为0.15,上述例子中用了AccelerateDecelerateInterpolator,计算公式为(input即为时间因子)

(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;

3.根据TypeEvaluator计算出在10ms时的属性值:0.15*(40-0)=6pixel。上例中TypeEvaluator为FloatEvaluator,计算方法为

public Float evaluate(float fraction, Number startValue, Number
endValue)
//参数分别为上一步的插值因子,开始值与结束值。
{
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}

1.3Property Animation和View Animation的关系

View Animation是比较旧的一套系统,仅仅适用于View对象。并且View Animation系统限制了可以动画的方面,比如缩放和旋转是可以的,但是背景颜色的动画是做不了的。View Animation系统的另一个缺陷就是它仅仅改变了View绘制的位置,并没有改变View本身实际的位置。比如,如果你让一个按钮通过动画移动到屏幕上的另一个位置,虽然它绘制在目标位置,但是你要点击它还是要在原来的位置,所以你需要自己写逻辑去处理这种问题。Property animation系统就不存在上面的问题,它是确实地改变了View对象的真实属性。

2.使用ValueAnimator创建动画

要获取ValueAnimator实例,可以通过调用它的工厂方法: ofInt(), ofFloat(), or ofObject()。例如:

public void ValueAnimRun(View view){    ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);    animation.setDuration(1000);    animation.start();}

布局文件为

<ImageView  android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_centerInParent="true" android:src="@drawable/bacground" android:scaleType="centerCrop" android:onClick="ValueAnimRun" />

ValueAnimator仅仅是计算动画过程中变化的值,并没有把这些计算出来的值应用到具体的对象上面,所以也不会有什么的动画显示出来。要把计算出来的值应用到对象上,必须为ValueAnimator注册一个监听器ValueAnimator.AnimatorUpdateListener,该监听器负责更新对象的属性值。在实现这个监听器的时候,可以通过getAnimatedValue()的方法来获取当前帧的值。

animator.addUpdateListener(new AnimatorUpdateListener()  {      @Override      public void onAnimationUpdate(ValueAnimator animation)      {                      }  });

3.使用ObjectAnimator创建动画

ObjectAnimator与ValueAnimator的区别是ObjectAnimator可以直接地把动画过程中计算出来的的值应用到一个具体对象的属性上,而ValueAnimator需要另外注册一个监听器来完成这个工作。所以使用ObjectAnimator就不再需要ValueAnimator.AnimatorUpdateListener了。

public void rotateyAnimRun(View view)  {      ObjectAnimator.ofFloat(view, "rotationX", 0.0F, 360.0F)      .setDuration(500)      .start();  } 

4.使用AnimatorSet编排多个Animator

有些时候,某些动画的开始需要依赖于其他动画的开始或结束,这时候就可以使用AnimatorSet来绑定这些Animator了。如:

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();

上面的代码片段,动画的执行顺序如下:
播放bounceAnim动画
同时播放squashAnim1, squashAnim2, stretchAnim1, and stretchAnim2
播放bounceBackAnim
播放fadeAnim

5.Animation监听器

你可以使用下面的监听器监听一些重要的事件:
Animator.AnimatorListener

  • onAnimationStart() - 动画启动时调用
  • onAnimationEnd() - 动画结束时调用
  • onAnimationRepeat() - 动画重新播放时调用
  • onAnimationCancel() - 动画被Cancel时调用. 一个被Cancel的动画也会调用onAnimationEnd()

ValueAnimator.AnimatorUpdateListener

  • onAnimationUpdate() - 在动画的每一帧上调用.
    在这个方法中,你可以使用ValueAnimator的getAnimatedValue()方法来获取计算出来的值。当然,这个监听器一般只适用于ValueAnimator。值得注意的是,你可能需要在这个方法中调用View.invalidate()方法来刷新屏幕的显示。

另外,还可以继承适配器 AnimatorListenerAdapter来代替对Animator.AnimatorListener的接口的实现,那么就只需要实现你所关心的方法了。如:

ValueAnimatorAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);fadeAnim.setDuration(250);fadeAnim.addListener(new AnimatorListenerAdapter() {public void onAnimationEnd(Animator animation) {    balls.remove(((ObjectAnimator)animation).getTarget());}

6.动画在ViewGroup布局改变时的应用

在ViewGroup布局发生改变的时候(如ViewGroup中的View消失或显示的时候),这个变化的过程你可能想要用动画的形式表现出来。ViewGroup通过方法setLayoutTransition(LayoutTransition)来设置一个布局转换的动画。 在LayoutTransition 上可以通过调用 setAnimator()方法来设置Animator,另外,还需要向这个方法传递一个 LayoutTransition标志常量,这个常量指示着在什么时候执行这个animator,可用的常量有:

  • APPEARING - 指示layout中的view正要显示的时候运行动画
  • CHANGE_APPEARING - 指示layout中因为有新的view加入而改变layout时运行动画
  • DISAPPEARING - 指示layout中的view正要消失的时候运行动画
  • CHANGE_DISAPPEARING - 指示layout中有view消失而改变layout时运行动画

如果你想要使用系统默认的ViewGroup布局改变时的动画,只需android:animateLayoutchanges 这个属性设置为true:

<LinearLayout  android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="match_parent" android:id="@+id/verticalContainer" android:animateLayoutChanges="true" />

7.自定义Evaluator

当IntEvaluator, FloatEvaluator, and ArgbEvaluator 这三种计算器都不能满足你的要求的时候,你可以通过实现 TypeEvaluator 接口的 evaluate()方法来自定义一个Evaluator。
下面是FloatEvaluator的evaluate()的实现:

public class FloatEvaluator implements TypeEvaluator {    public Object evaluate(float fraction, Object startValue, Object endValue) {        float startFloat = ((Number) startValue).floatValue();        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);    }}

8.自定义Interpolator

自定义Interpolator是通过实现TimeInterpolator 的getIntepolation(float)方法来实现的。下面展示的分别是AccelerateDecelerateInterpolator和LinearInterpolator的具体实现,其中input为Elapsed fraction(时间因子):
AccelerateDecelerateInterpolator:

public float getInterpolation(float input) {    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}

LinearInterpolator:

public float getInterpolation(float input) {    return input;}

9.使用Keyframes方式创建动画

Keyframe 对象由elapsed fraction/value对组成。 Keyframe 对象还可以使用插值器。下面是示例:

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(5000ms);

10.使用ViewPropertyAnimator创建动画

使用ViewPropertyAnimator可以很方便地根据View的多个属性值创建动画。下面用多个ObjectAnimator方式、单个ObjectAnimator方式和ViewPropertyAnimator方式创建View多属性变化的动画作对比。

  • Multiple ObjectAnimator objects:
ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);AnimatorSet animSetXY = new AnimatorSet();animSetXY.playTogether(animX, animY);animSetXY.start();
  • One ObjectAnimator:
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);

11.通过XML方式声明Animator

可以在res/animator目录下声明Property Animation的动画(注意不是res/anim,它是View Animation框架的资源目录)
Animator类与标签元素的对应关系:

  • ValueAnimator - animator
  • ObjectAnimator - objectAnimator
  • AnimatorSet - set
    下面是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>

为了能够运行上面声明的animator,必须在代码中使用AnimatorInflater的inflate方法来实例化xml声明的animator,如:

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

参考

http://blog.csdn.net/sin90lzc/article/details/7517837
http://blog.csdn.net/lmj623565791/article/details/38067475
http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html
http://blog.csdn.net/lmj623565791/article/details/38092093

更多相关文章

  1. Android framework修改----关屏动画效果
  2. Android 解决帧动画卡顿问题
  3. Android 动画效果设置
  4. android Frame动画基础
  5. Fresco属性
  6. Lottie动画
  7. Android 关于动画设置问题。

随机推荐

  1. Windows上搭建android开发环境
  2. Android IOS WebRTC 音视频开发总结(十五)-
  3. Android异步加载图像小结
  4. Android Ant更新项目
  5. 系出名门Android(8) - 控件(View)之TextS
  6. android中 google map计算两GPS点间距离
  7. Android实现TextView字符串波浪式跳动
  8. 页面未随软键盘上升及android隐藏软键盘
  9. Android异步更新UI-线程池-Future-Handle
  10. Android(安卓)wifi设计原理(源码分析)