android动画详解五 layout,插值与评估器

来源:互联网 发布:js 获取端口号 编辑:程序博客网 时间:2024/06/05 20:49

· 动画监听器

 

你可以使用下述监听器监听动画过程中的重要事件们: 

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

· 动画ViewGroups的Layout变化

 

属性动画系统提供了动画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

· 使用一个TypeEvaluator

 

如果你想去动画一个Android系统不知道的类型,你可以创建你自己的 evaluator,这需要实现TypeEvaluator  口。Android系统知道的类型有intfloatcolor,分别被IntEvaluatorFloatEvaluatorArgbEvaluator 所支持。

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 开始时加速,结束时减速。下面的方法们定义了此种插值器的逻辑:

//AccelerateDecelerateInterpolatorpublic float getInterpolation(float input) {    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;}//LinearInterpolatorpublic 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动画详解六 XML中定义动画


Android很多时候要用NDK开发,对于C语言不是很熟悉的小伙伴,可以看一下本人录制的视频教程:http://edu.csdn.net/course/detail/2057

c++入门群:535807023

android讨论群:209796692

1 1