本文是对Android动画API的官方资料的翻译。
原文连接:https://developer.android.com/guide/topics/graphics/prop-animation.html
以下正文开始:
属性动画
- 持续时间(Duration):动画时长,默认为300 ms。
- 时间插值(Time interpolation):属性值随时间的函数变化关系。
- 重复计数与模式(Repeat count and behavior):可以指定当动画结束时是否需要重复动画以及重复次数;也可以指定动画逆向进行,也可以设置正向逆向重复直到达到重复次数。
- 动画集合(AnimationSet):你可以定义一组动画集合,同时执行或者顺序执行。
- 帧刷新延迟(Frame refresh delay):定义多久刷新一次动画帧。默认值每10ms刷新一次,但是刷新的速度最终取决于系统繁忙与否以及底层定时器的的速度。
属性动画如何工作
属性动画与视图动画的区别
API 概览
| Class | 描述 |
| ValueAnimator | 属性动画主要的定时机制,同时计算属性。该类包含所有核心功能,并包含计算动画值、每个动画的定时细节、是否重复的信息、接受更新事件的监听器、设置自定义类型。产生动画分为两部分:计算动画值 和 将值赋予对象属性。ValueAnimator并不实现第二部分,所以你必须监听ValueAnimator计算得到的值,然后通过自己的逻辑来实现动画。查看更多信息见Animating with ValueAnimator。 |
| ObjectAnimator | ValueAnimator的子类,可以设定目标对象及目标属性。当该类计算好动画的新值时,相应地更新属性值。因为ObjectAnimator更新目标对象的属性动画值更加简单,所以大多数时候要使用该类。然而有时候需要直接使用ValueAnimator,因为ObjectAnimator有更多的限制,比如目标对象上需要特定的访问器方法。 |
| AnimatorSet | 提供动画分组机制,这样它们之间可以以某种关系运行。你可以指定这些动画同时运行,顺序执行,或者以一定的延迟来执行。常看更多信息见Choreographing multiple animations with AnimationSets |
| Class/Interface | Description |
| IntEvaluators | 计算int 属性值的默认evaluator |
| FloatEvaluation | 计算float属性值的默认evaluator |
| ArgbEvaluation | 计算颜色属性的默认evaluator(十六进制) |
| TypeEvaluator | 创建自定义evaluator的接口。如果要产生动画的属性既不是int,float或者color,你必须实现TypeEvaluator接口来指定如何计算对象属性的动画值。如果你想改变int,float,color这些类型的默认行为,也可以给指定自定义的TypeEvaluator。查看更多信息写自定义详见-->Using a TypeEvaluator |
| Class/Interface | Description |
| AccelerateDecelerateInterpolator | Interpolator:开始和结束的时候变化很慢,但中间会加速 |
| AccelerateInterpolator | Interpolator:开始很慢,然后不断加速 |
| AnticipateInterpolator | Interpolator:whose change starts backward then flings forward(大意是,开始向后再向前) |
| AnticipateOvershootInterpolator | Interpolator:开始向后再向前,但是超过目标值,再回退到final value |
| BounceInterpolator | Interpolator:动画结束时候有反弹 |
| CycleInterpolator | Interpolator:动画以指定的循环数循环 |
| DecelerateInterpolator | Interpolator:开始很快,然后开始减速 |
| LinearInterpolator | Interpolator:匀速改变 |
| OvershootInterpolator | Interpolator:向前甩,超过最终值后再返回 |
| TimeInterpolar | 接口:可以实现自己的Interpolator |
ValueAnimator 实现动画
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
animation.setDuration(1000);
animation.start();在上述代码中,ValueAnimator开始在0和1之间计算动画值,持续时间1000 ms,调用start() 方法开始执行。
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();在上述代码中,ValueAnimator利用MyTypeEvaluator中实现的逻辑计算startPropertyValue到endPropertyValue之间的动画值。持续时间1000 ms,调用start() 方法开始执行。
之前的代码段并没有对对象有真正的影响,因为ValueAnimator并没有直接操作对象及属性。但是你最想做的是利用计算出来的数据来改变对象,产生动画。你可以在ValueAnimator中定义一个监听器来处理动画生命周期中的重要事件,比如框架的更新(Frame updates)。当实现监听器后,你可以通过调用getAnimatedValue() 方法来获取指定框架刷新需要的计算值。listener的更多信息,详见---> Animation Listener
ObjectAnimator实现动画
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
anim.setDuration(1000);
anim.start();为了使ObjectAnimator正确的更新属性,需要做以下几项:
- 对象属性必须有个setter函数,形式为set<属性名>()。因为ObjectAnimator自动更新属性,所以必须能通过setter方法来获取属性。比如,属性名为 foo,你需要一个setFoo()方法。如果setter方法不存在,你有三种选择:
- 如果可以,加setter方法;
- 使用一个你能更改的封装类,这个封装类通过一个有效的setter方法接收值然后转寄给原始对象。
- 使用ValueAnimator代替
- 如果你在ObjectAnimator工厂方法中为values...仅指定一个值,那么把其假定为ending value。所以你要操作的对象属性要有一个getter()方法来获取动画的初始值。getter()方法的形式必须是get<属性名>(),比如属性名是 foo,需要一个getFoo()方法。
- 属性的getter(如果需要)和setter方法必须操作同一类型(即为ObjectAnimator指定的初始值和结束值),举个例子,你必须用targetObject.setPropName(float)和targetObject.getPropName(float),当你使用了下述构造方法:
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
- 根据产生动画的对象或属性,你有可能(might)需要调用View的invalidate()方法来强制屏幕以更新后的属性值来重绘。你要在onAnimationUpdate()回调中完成。例如,让一个Drawable对象的color属性产生动画,只有在重绘的时候才能在屏幕上更新。所有关于View的属性setters,比如setAlpha()和setTranslationX(),invalidate the View properly,所以在调用这些方法赋予新值时无需再invalidate the View。
利用Animation创建多动画
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();
Animation 监听器
你可以使用下列监听器来监听动画持续时间内的重要事件:- Animator.AnimatorListener
- onAnimationStart() - 动画开始时调用
- onAnimationEnd() - 动画结束时调用
- onAnimationRepate() - 动画重复时调用
- onAnimationCancel()- 动画取消时调用,同时会调用onAnimationEnd()方法(无论何种方式停止都会被调用)。
- ValueAnimator.AnimationUpdateListener
- onAnimationUpdate() - 被动画的每一帧调用,监听该事件来使用ValueAnimator计算好的值。为了使用该值,通过ValueAnimator对象的getAnimatedValue()方法来获得。如果使用ValueAnimator,需要实现该监听器接口。
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());
}
Animating Layout Changes to ViewGroups
属性动画可以animate changes to ViewGroup objects ,也提供了简单的方法使View对象产生动画。- APPEARING - 条目加入到容器中动画标志位
- CHANGE_APPEARING - 由于新条目加入,其他条目移动动画的标志位
- DISAPPEARING - 条目从容器中移除时的动画标志位
- CHANGE_DISAPPEARING - 由于条目移出,其他条目移动的动画标志位
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/verticalContainer"
android:animateLayoutChanges="true" />将此属性设定为true,自动地加入Views加入或移除的动画,以及ViewGroup中剩余Views的动画效果。
使用TypeEvaluator
如果你要对Android系统不”能识别“的类型产生动画,你可以通过实现TypeEvaluator接口来实现自己的evaluator。Android”能识别“的类型有int、float和color,分别对应IntEvaluator,FloatEvaluator和ArgbEvaluator三种类型的evaluator。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之间),然后根据使用的Interpolator来计算插值,插值分数是你的TypeEvaluator接受到的fraction参数。所以计算动画值时你不必考虑Interpolator。
使用Interpolator
Interpolator定义了特定值与时间的函数关系。比如你可以指定整个动画线性执行,也就是整个动画阶段动画均匀移动;或者指定动画非线性执行,比如使用加速或者减速在动画的开始或者结尾。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动画中interpolators计算的近似值:
| ms elapsed | Elspased 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 |
指定关键帧(KeyFrames)
关键帧对象包含一个时间/值 对,使你可以定义特定时间的动画的特定状态。每个keyframe也可以有自己的Interpolator,来控制前一个关键帧到该关键帧的动画行为。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);更多使用keyframe的完整的例子,见--->
MultiPropertyAnimation
Animating Views
- translationX 和 translationY:该特性控制View定位时,相对于布局容器中设定值的偏移量
- rotation, rotationX, rotationY:这些属性控制围绕基准点的2D,3D旋转
- scaleX, scaleY:这些属性控制围绕基准点的2D缩放
- pivotX, pivotY:这些属性控制基准点的坐标,rotation和scaling变换中出现,默认基准点在对象的中心
- x 和 y:这是简单实用的属性来描述View在容器中的最终位置,为left值,top值和translationX和translationY值的和
- alpha:代表View的alpha透明度,默认为1,0表示完全透明(不可见)
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
使用ViewPropertyAnimator产生动画
ViewPropertyAnimator提供了简单的方法来并行操作一个view的多个属性。他的功能很想ObjectAnimator,因为它改变view属性的实际值,但是同时操作多个动画属性就不太一样。另外,使用ViewPropertyAnimator的代码更加简洁,方便阅读。以下代码片段展示了使用multiple ObjectAnimator,single ObjectAnimator,和ViewPropertyAnimator同时改变view的x 与 y属性: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);
在XML中声明动画
属性动画允许在XML中声明动画,在XML中定义动画,可以在对个Activities中重复使用,而且更加简单的编辑动画序列。- ValueAnimator - <animator>
- ObjectAnimator - <objectanimator>
- Animator - <set>
<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>为了执行动画,你必须在代码中将XML文件inflate到一个AnimationSet对象中,然后在动画开始前要指定所有动画的目标对象。调用setTarget()方法来快捷地为该AnimationSet的所有子动画指定一个目标对象。下面代码展示了如何做:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();更多定义属性动画的XML语法,详见--->
Animation Resource
9612



被折叠的 条评论
为什么被折叠?



