你可以使用下述监听器监听动画过程中的重要事件们:
· Animator.AnimatorListener
· onAnimationStart() - 动画开始时调用。
· onAnimationEnd() - 当动画结束时调用。
· onAnimationRepeat() - 当动画开始重复时调用。
· onAnimationCancel() - 当动画被取消时调用。一个取消的动画还调用onAnimationEnd(),不论他是怎样结束的。
· ValueAnimator.AnimatorUpdateListener
· onAnimationUpdate() - 动画的每帧都调用一次。监听此事件来使用ValueAnimator在动画中产生的值。要使用此值,调用方法getAnimatedValue() 。当使用ValueAnimator时,此监听器是必须的。
跟据动画的对象和属性的不同,你可能需要调用View的invalidate()方法来强制屏幕使用更新的动画数据重绘自己。你应在onAnimationUpdate() 回调中这样做。例如,动画一个Drawable对象的color属性导致仅在对象重绘自己时才更新屏幕。View的所有的属性setter,比如setAlpha()和setTranslationX(),都会使View无效,所以你不需要在调用这些方法时使View无效。
如果你不想实现Animator.AnimatorListener 的所有的方法,你可以从类AnimatorListenerAdapter派生而不是实现接口 Animator.AnimatorListener 。类 AnimatorListenerAdapter提供了你可以覆写的方法们的空实现。
例如,API Demo中的Bouncing Balls例子创建了一个AnimatorListenerAdapter仅仅重写了onAnimationEnd()回调。
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()); }
属性动画系统提供了动画ViewGroup对象的能力,就象动画View对象那么容易。
你可以使用类LayoutTransition 动画一个ViewGroup中的布局 。ViewGroup 中的Views可以在你添加或删除或显示或隐藏时动画其过程 。ViewGroup 已存在的View们也可以动画移动位置的过程。你可以在一个LayoutTransition 对象中定义动画。你需调用setAnimator() 并传入一个带有以下任意一个LayoutTransition 常量的Animator 对象:
· APPEARING – 表明动画是作用于在容器中新出现的对象上的。
· CHANGE_APPEARING – 表明动画应用于一个当新对象出现时发生改变的对象。
· DISAPPEARING - 表明动画作用于一个正在消失的对象。
· CHANGE_DISAPPEARING – 表明动画作用于一个在另一个对象消失时发生改变的对象。
你可以为四种事件定义你自己的动画来个性化layout的变化过程,或仅仅告诉动画系统使用默认的动画。
API Demos 中的LayoutAnimations 例子向你演示了如何定义layout变化动画然后设置给要动画的View对象。
LayoutAnimationsByDefault 和它对应的layout_animations_by_default.xml layout资源文件向你展示了如何在XML 中为ViewGroups 启用默认的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" />
设置此属性为true会动画向ViewGroup 添加或删除的Views和已存在的Views。
如果你想去动画一个Android系统不知道的类型,你可以创建你自己的 evaluator,这需要实现TypeEvaluator 接 口。Android系统知道的类型有int, float, 和color,分别被IntEvaluator, FloatEvaluator, 和ArgbEvaluator 所支持。
在TypeEvaluator 接口中只有一个方法需要实现: evaluate() 。用它向animator返回所动画的属性的在当前动画时间点的值。FloatEvaluator 类演示了如何做到:
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); } }
注: 当ValueAnimator (或 ObjectAnimator) 运行时,它会计算当前动画经过时间的比例(一个0和1之间的值),然后跟据你使用的插值器计算出一个插入值。这个插入值是一个分数,它就是你的TypeEvaluator 所接收的fraction参数,所以你不必担心计算动画值时的插值问题。
一个插值器定义了如何计算动画中的某个特定的值。例如,你可以指定动画线性的进行,表示动画总是均匀的运动,或者你也可以指定动画使用非线性时间,例如,开始加速结束时减速。
动画系统中的插值器从Animator接收一个代表所经历时间的分数。插值器修改此值,使其与所提供的动画类型相一致。Android系统在包 android.view.animation package中提供了一系列的通用插值器。如果这些还不能满足你,你可以实现TimeInterpolator 接口来创建你自己的插值器。
作为一个例子,下面对比了 AccelerateDecelerateInterpolator 和LinearInterpolator 如何计算插出来的分数。 LinearInterpolator 对代表所经历时间的分数没么影响。 AccelerateDecelerateInterpolator 开始时加速,结束时减速。下面的方法们定义了此种插值器的逻辑:
//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; }
下表代表了一个持续1000ms的动画被这些插值器计算出的值。
ms elapsed |
Elapsed fraction/Interpolated fraction (Linear) |
Interpolated fraction (Accelerate/Decelerate) |
0 |
0 |
0 |
200 |
.2 |
.1 |
400 |
.4 |
.345 |
600 |
.6 |
.8 |
800 |
.8 |
.9 |
1000 |
1 |
1 |
如上表所示,LinearInterpolator 以不变的速度改变着值,每200ms 增加.2 ,AccelerateDecelerateInterpolator 在 200ms 和 600之间改变的值快于LinearInterpolator ,而在600ms 和1000ms之间慢于它。
一个Keyframe对象是由键-值对构成的,使你可以定义动画的一个特殊时间。每个keyframe都可以具有自己的插值器来控制从上一个keyframe到这个keyframe的动画行为。
要实例化一个Keyframe 对象,你必须使用某个工厂方法 ofInt(), ofFloat(), 或 ofObject() 来取得Keyframe 的合适的类型。之后你调用 ofKeyframe() 工厂方法获得一个 PropertyValuesHolder 对象。一旦你具有了此对象,你就可以通过传入PropertyValuesHolder 对象和要动画的对象获得一个animator。下面的代码片段演示了如何实现:
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);
更多的使用使用keyframes的例子,见APIDemos 中的示例MultiPropertyAnimation 。
上一篇:android动画详解四 创建动画
Android很多时候要用NDK开发,对于C语言不是很熟悉的小伙伴,可以看一下本人录制的视频教程:http://edu.csdn.net/course/detail/2057
c++入门群:535807023
android讨论群:209796692