[TOC]
Property Animation
属性动画系统是一个强大的框架,几乎可以将任何东西动画化。您可以定义一个动画以随时间更改任何对象属性,而不管它是否绘制到屏幕。属性动画在指定的时间长度内更改属性(对象中的字段)值。你可以指定要动画的对象属性。例如对象在屏幕上的位置,要为其设置动画的时间长度以及要在其间进行动画化的值。
属性动画系统允许开发者定义动画的以下特征:
- 1:Duration:你可以指定动画的持续时间。
默认长度为300 ms。 - 2:Time interpolation:你可以指定如何根据动画当前所用时间计算属性的值。
- 3:Repeat count and behavior: 你可以指定是否在到达持续时间结束时重复播放动画,以及重复播放动画的次数。 还可以指定是否要相反地播放动画。 将其设置为反向播放动画向前,然后反复向后,直到达到重复次数。
- 4:Animator sets:您可以将动画组合成Sets,可以设置Sets的播放方式,一起播放或顺序播放或在指定的延迟之后。
- 5:Frame refresh delay:你可以指定刷新动画帧的频率。 默认设置为每10 ms更新一次,但是应用程序刷新帧的速度最终取决于系统整体的繁忙程度,以及系统可以为底层定时器服务的速度。
Property Animation 的工作原理:
首先,我们来通过一个例子查看一下动画是如何工作的,图1描绘了一个假设的对象,是x属性水平移动的动画。动画的持续时间设置为40 ms,行程距离为40像素。 每10 ms,这是默认的帧刷新率,对象水平移动10像素。 在40 ms结束时,动画停止,物体以水平位置40结束。这是具有线性插值的动画的示例,意味着物体以恒定的速度移动。
你还可以指定具有非线性内插的动画。图2示出了对象在动画开始时加速,并且在动画结束时减速。 物体仍然在40毫秒内移动40像素,但是非线性。 一开始,这个动画加速到中途,然后从中途减速直到动画结束。 如图2所示,动画开头和结尾处的距离小于中间。
我们来详细了解属性动画系统的重要组件如何计算动画,如图所示:
ValueAnimator对象跟踪动画的时间,例如动画已运行多长时间,以及动画所属属性的当前值。ValueAnimator封装了TimeInterpolator,它定义了动画插值,还有一个TypeEvaluator,它定义了如何计算动画属性的值。例如,在图2中,使用的TimeInterpolator将为AccelerateDecelerateInterpolator,TypeEvaluator将为IntEvaluator。
要启动动画,创建一个ValueAnimator,并为其创建动画的属性、动画持续时间以及它的开始和结束值,然后调用start()方法开始动画。在整个动画过程中,ValueAnimator根据动画的持续时间和经过多少时间,计算0到1之间的经过分数。经过的分数表示动画完成的时间百分比,0表示0%,1表示100%。
例如,在图1中,t = 10ms时的经过分数为0.25,因为总持续时间为t =40ms。当ValueAnimator完成计算经过的分数时,它调用当前设置的TimeInterpolator,以计算内插分数(编者按:不是有个插值器么,定义了动画的快慢方式,比如匀速,先加速后减速)。将经过的时间分数映射到考虑到插值的新分数(编者按:最后根据这个新分数来计算实际的百分比,在上面是实际的运动距离)。例如,在图2中,由于动画缓慢加速,所以在t= 10 ms时,内插分数约为.15,小于经过的时间分数.25。 在图1中,插值分数总是与经过分数相同。
当计算插值分数时,ValueAnimator将根据插值分数,起始值和动画的结束值,调用相应的TypeEvaluator来计算您要动画化的属性值。 例如,在图2中,t = 10 ms时插值分数为.15,因此此时的属性值为.15 X(40 - 0)或6。
Property Animation与View Animation有哪些不同
Android 的ViewAnimation系统只提供了给View对象动画处理的功能,因此,如果你想为非View对象设置动画效果,则必须自己去实现相关代码。ViewAnimation系统本身也有限制,它只将View的几个方面暴露出来让我们来实现动画,例如视图的缩放和旋转,但是并没有提供给我们背景颜色(编者按:背景颜色属于View的属性,我们可以使用属性动画来控制它)。
ViewAnimation系统的另一个缺点是它只修改了View的绘制位置,而不是实际的View本身。例如,如果你通过ViewAnimation系统实现一个按钮在屏幕上移动的动画,则动画可以正确绘制,但你可以单击按钮的实际位置不会更改(编者按:也就你点击的区域不会改变,你可以自己实现来看,虽然View移动了,但是点击区域还是原来的位置),因此你需要来处理此问题(编者按:如果你知识需要一个动画,这样就可以了)。
使用属性动画的话,就没有上面所说的问题。你可以对任何对象(视图和非视图)的任何属性进行动画处理,并且对象本身实际上进行了修改。属性动画系统在执行动画的方式也更加强大。在高级别上,你可以分配animators (编者按:这个地方官方给的是animators)给你想要执行动画的属性,例如颜色,位置或大小,并且可以定义动画的方面(aspects),例如多个animators的插值(编者按:插值器)和同步。然而,View Animation系统需要较少的时间来设置,并且需要较少的代码来写入。如果View Animation系统就可以完成了你想要的动画效果,则不需要使用属性动画。如果使用情况出现的话(编者按:个人认为是如果需要的话),在不同情况下使用这两种动画系统也是有意义的。
用ValueAnimator进行动画处理
ValueAnimator类允许你通过指定一组int,float或颜色值来动画化。通过调用其中一种工厂方法获取ValueAnimator:ofInt(),ofFloat()或ofObject()。例如:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();
(编者按:这里只是对值进行了处理,并没有涉及到目标对象以及我们要操作的属性)
在此代码中,当start()方法运行时,ValueAnimator将开始计算0到100之间的动画值,持续时间为1000 ms。
你还可以通过执行以下操作来指定自定义类型进行动画处理:
ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();
(编者按:这里需要我们自己去计算实际的动画值,你传入的是object,系统又不知道该怎么去帮你计算,所以只能自行处理,这里是用MyTypeEvaluator继承自TypeEvaluator来进行处理)
在此代码中,当start()方法运行时,ValueAnimator将使用MyTypeEvaluator提供的逻辑持续1000 ms,在startPropertyValue和endPropertyValue之间开始计算动画值。
你可以通过向ValueAnimator对象添加AnimatorUpdateListener来使用动画值,如以下代码所示:
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
// You can use the animated value in a property that uses the
// same type as the animation. In this case, you can use the
// float value in the translationX property.
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
在onAnimationUpdate()方法中,您可以访问更新的动画值,并在其中一个视图的属性中使用它。
用ObjectAnimator进行动画处理
ObjectAnimator是ValueAnimator的一个子类,将ValueAnimator的定时引擎和值计算与将目标对象的命名属性动画化的能力相结合。这使得动画化任何对象更容易,因为不再需要实ValueAnimator.AnimatorUpdateListener,因为动画属性会自动更新。
实例化一个ObjectAnimator类似于一个ValueAnimator,但是您还可以指定该对象的属性(作为一个字符串)的名称以及值之间的动画值:
ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();
要使ObjectAnimator正确更新属性,必须执行以下操作:
一、正在动画的对象属性必须以set
例如,如果属性名称为foo,则需要具有setFoo()方法。如果此setter方法不存在,有三个选项:
- 1:如果有权这样做,将setter方法添加到类中。
- 2:使用有权更改的包装类,并使该包装器使用有效的setter方法接收该值并将其转发到原始对象。
- 3:改用ValueAnimator。
二:如果在ObjectAnimator的方法之一中为values ...参数只指定了一个值,那么那个值假定是动画的结束值。因此,您正在动画的对象属性必须具有用于获取动画起始值的getter函数。 getter函数必须以get
三:要动画的属性的getter(如果需要)和setter方法必须与您指定给ObjectAnimator的起始值和结束值有相同的类型。例如,如果构造以下ObjectAnimator,则必须具有targetObject.setPropName(float)和targetObject.getPropName(float):
ObjectAnimator.ofFloat(targetObject, "propName", 1f)
四:根据您所动画的属性或对象,您可能需要在视图上调用invalidate()方法来强制屏幕使用更新的动画值重新绘制自己。你可以在onAnimationUpdate()回调中执行此操作。例如,动画化Drawable对象的color属性只会导致在Drawable对象重新绘制时更新屏幕。View上的所有属性setter(如setAlpha()和setTranslationX())都会使View无效,因此在使用新值调用这些方法时,不需要使View无效。 有关侦听器的更多信息,请参阅有关动态侦听器的部分。
使用AnimatorSet来控制多个动画
在许多情况下,你想要播放依赖于其他动画开始或结束的动画。Android系统允许将动画捆绑在一起成AnimatorSet,以便可以指定是同时,顺序还是在指定的延迟之后启动动画。 您也可以将AnimatorSet对象嵌套在彼此中。
从弹跳球Demo(为了简化而有所修改)获取的以下示例代码以下列方式展示下列的Animators。
- 1:Plays bounceAnim
- 2:Plays squashAnim1,squashAnim2,stretchAnim1和stretchAnim2。
- 3:Plays bounceBackAnim.
- 4:Plays fadeAnim.
有关如何使用动画组合的更完整的示例,请参阅APIDemos中的 Bouncing Balls示例。
Animation Listeners
你可以在动画持续时间内收听下面介绍的listeners 的重要事件。
一:Animator.AnimatorListener
- 1:onAnimationStart() - 动画启动时调用。
- 2:onAnimationEnd() - 动画结束时调用。
- 3:onAnimationRepeat() - 当动画重复时调用。
- 4:onAnimationCancel() - 当动画被取消时调用。 取消的动画也会调用OnAnimationEnd(),无论它们如何结束。
二:ValueAnimator.AnimatorUpdateListener
onAnimationUpdate() - 在动画的每个帧上调用。(默认的帧刷新率是10ms每次),监听此事件以使用ValueAnimator在动画期间生成的计算值。要使用该值,使用传递给事件的ValueAnimator对象的getAnimatedValue()方法获取当前动画值。 如果你使用ValueAnimator,则需要实现此监听器。
根据你要动画的属性或对象,您可能需要在视图上调用invalidate(),以强制屏幕区域使用新的动画值重新绘制。 例如,当Drawable对象重新绘制时,可以对Drawable对象的color属性进行动画化,只会导致屏幕更新。 View上的所有属性setter(如setAlpha()和setTranslationX())都会使View无效,因此在使用新值调用这些方法时,不需要使View无效。(前面已经介绍过了)
如果你不想实现Animator.AnimatorListener接口的所有方法,可以扩展AnimatorListenerAdapter类。 AnimatorListenerAdapter类提供了可以选择覆盖的方法的空实现。
(编者按:你如果实现Animator.AnimatorListener接口接口的话需要实现下面这四个方法。
void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation);
void onAnimationRepeat(Animator animation);
如果你不想实现这么多的话,比如你只需要一个的实现,你就可以使用AnimatorListenerAdapter类,这个类继承自Animator.AnimatorListener接口和Animator.AnimatorPauseListener接口,这个接口里有两个方法
void onAnimationPause(Animator animation);
void onAnimationResume(Animator animation);
所以AnimatorListenerAdapter类里面有上面六个方法的实现,你可以任意选择一个来进行实现)
谷歌官方给了个栗子:
ValueAnimator 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
属性动画系统提供了对ViewGroup对象进行动画更改的功能,同时也为View对象本身提供了一种简单的方法。
你可以使用LayoutTransition类为ViewGroup中的布局设置更改动画。ViewGroup中的View可以在ViewGroup中添加或从ViewGroup中删除时或当你使用VISIBLE,INVISIBLE或GONE调用View的setVisibility()方法时,看到出现和消失的动画。当你添加或删除视图时,ViewGroup中的其余视图也可以动画的进入它们新的位置。
你可以通过调用setAnimator()并传递Animator对象和传递在LayoutTransition对象中定义以下常亮之一来设置动画:
LayoutTransition 类中定义的常数:
- 1:APPEARING - 指示在容器中出现的项目上运行的动画的标志。
- 2:CHANGE_APPEARING - 指示由于容器中出现新项目而改变的项目上运行的动画的标志。
- 3:DISAPPEARING - 表示在从容器中消失的项目上运行的动画的标志。
- 4:CHANGE_DISAPPEARING - 指示由于项目从容器中消失而改变的项目上运行的动画的标志。
(编者按:setAnimator源码如下:)
public void setAnimator(int transitionType, Animator animator) {
switch (transitionType) {
case CHANGE_APPEARING:
mChangingAppearingAnim = animator;
break;
case CHANGE_DISAPPEARING:
mChangingDisappearingAnim = animator;
break;
case CHANGING:
mChangingAnim = animator;
break;
case APPEARING:
mAppearingAnim = animator;
break;
case DISAPPEARING:
mDisappearingAnim = animator;
break;
}
}
你可以为这四种类型的事件定义自己的动画,以及自定义布局转换的外观,或者只是告诉动画系统使用默认动画。API Demos中的LayoutAnimations示例显示了如何为布局转换定义动画,然后在要动画化的View对象上设置动画。
LayoutAnimationsByDefault及其相应的layout_animations_by_default.xml布局资源文件显示如何启用XML中ViewGroups的默认布局转换。 你唯一需要做的是为ViewGroup设置android:animateLayoutchanges属性为true。 例如:
将此属性设置为true将自动生成从ViewGroup添加或删除的视图以及ViewGroup中的其余视图的动画。
Using a TypeEvaluator
如果要为Android系统未知的类型设置动画,您可以通过实现TypeEvaluator接口来创建自己的evaluator 。Android系统已知的类型是int,float或颜色,分别对应IntEvaluator,FloatEvaluator和ArgbEvaluator类型。
在在TypeEvaluator接口中只有一种方法,那就是evaluate()方法。这允许您使用的animator 在动画的当前位置为动画属性返回适当的值。
(编者按:接口源码如下)
public interface TypeEvaluator {
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction
representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (x1 - x0)
,
* where x0
is startValue
, x1
is endValue
,
* and t
is fraction
.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);
}
FloatEvaluator类:
/**
* This evaluator can be used to perform type interpolation between float
values.
*/
public class FloatEvaluator implements TypeEvaluator {
/**
* This function returns the result of linearly interpolating the start and end values, with
* fraction
representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: result = x0 + t * (v1 - v0)
,
* where x0
is startValue
, x1
is endValue
,
* and t
is fraction
.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value; should be of type float
or
* Float
* @param endValue The end value; should be of type float
or Float
* @return A linear interpolation between the start and end values, given the
* fraction
parameter.
*/
public Float evaluate(float fraction, Number startValue, Number endValue) {
float startFloat = startValue.floatValue();
return startFloat + fraction * (endValue.floatValue() - startFloat);
}
}
(编者按:这个地方跟官方的不一样,这里我才用的是API25的源码,可以看出这就是一个小学的计算。。。)
注意:当ValueAnimator(或ObjectAnimator)运行时,它会计算动画的当前经过分数(0到1之间的值),然后根据所使用的内插器计算出考虑到插值器的插值分数(也就是实际的运行分数)。 插值分数是您的TypeEvaluator通过分数参数获得的分数,因此在计算动画值时不需要考虑插值器。
Using Interpolators
插值器定义如何根据时间的函数计算动画中的特定值。 例如,你可以指定动画在整个动画中线性发生,这意味着动画在整个时间内均匀移动,或者你可以指定使用非线性时间的动画,例如,在开始或结束时使用加速或减速 动画。动画系统中的插值器从Animators接收代表动画经过时间的分数。插值器修改这个分数(这个分数只和时间相关),以符合它在提供的类型。(编者按:在源码中有两个分数,一个是在插值器之前的,这个分数只和时间相关,另一个是经过插值器修改过的,这个就是实际运行的分数,只有在匀速运动的时候两个分数是相同的)。
Android系统在android.view.animation包中提供了一组常见的插件。 如果这些都不符合您的需求,您可以实现TimeInterpolator界面并创建自己的。
例如,下面比较默认提供的插值器AccelerateDecelerateInterpolator和LinearInterpolator计算插值分数的不同。
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 | Linear | Accelerate/Decelerate |
---|---|---|
0 | 0 | 0 |
200 | 0.2 | 0.1 |
400 | 0.4 | 0.345 |
600 | 0.6 | 0.8 |
800 | 0.8 | 0.9 |
1000 | 1.0 | 1.0 |
Specifying Keyframes
(编者按:先来看一下源码对于Keyframes是怎么定义的-->该类保存动画的时间/值对。)
一个Keyframes保存一个时间/值对,在开发者定义的一个特定状态在动画的特定时间。每一个keyframe也能够拥有自己的插值器在前一个keyframe和这个keyframe的时间间隔内去控制动画的行为。
要实例化一个Keyframe 对象,你必须使用一个工厂方法,即ofInt(),ofFloat()或orObject()来获取Keyframe的适当类型。(编者按:整篇文章对ofInt等方法都成为factory methods,有知道的朋友可以给我留言)
然后调用ofKeyframe()方法来获取一个PropertyValuesHolder对象。一旦拥有该对象,你可以通过传递PropertyValuesHolder对象和the object获得一个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);
有关如何使用keyframe的更完整的示例,请参阅APIDemos中的MultiPropertyAnimation示例。
Animating Views
属性动画系统允许View对象的流线型动画,并且相比视图动画系统有很多优点。视图动画系统通过更改绘制方式来转换View对象。这是在每个视图的容器中处理的,因为View本身没有要处理的属性。这导致View被动画化,但是在View对象本身没有改变。这导致即使它被绘制在屏幕上的不同位置,对象仍然存在于其原始位置的行为。(编者按:之前提到过,点击区域并没有发生任何的变化),在Android 3.0中,添加了新的属性和相应的getter和setter方法来消除这个缺点。
通过更改View对象中的属性,属性动画系统可以在屏幕上动画化视图。 另外,Views也会自动调用invalidate()方法,以便在其属性更改时刷新屏幕(编者按:invalidate()方法会调用draw方法进行重新绘制,在是用Scroller实现弹性动画的时候会使用到这一点)。
View中便于属性动画的新属性有:
- 1:translationX and translationY 这些属性控制视图位于其左侧和顶部坐标中由其布局容器设置的三角形。(编者按:我自己的理解是移动前View的左上角和移动后View的左上角组成的三角形,对不对不清楚)
- 2:rotation, rotationX, and rotationY:这些属性控制2D(旋转属性)中的旋转和绕枢轴点的3D旋转。
- 3:scaleX and scaleY:这些属性控制视图围绕其枢轴点的2D缩放。
- 4:pivotX and pivotY: 这些属性控制枢轴点的位置,旋转和缩放变换中心都是在该位置。 默认情况下,枢轴点位于对象的中心。
- 5:x and y:这些是简单的实用属性,用于在其容器中描述View的最终位置,作为mLeft和mTop以及translationX和translationY值之和。
- 6:表示视图上的Alpha透明度。 默认值为1(不透明),值为0表示完全透明(不可见)。
要为View对象的属性(如其颜色或旋转值)设置动画效果,您需要做的是创建一个属性动画制作器,并指定要设置动画的View属性。 例如:
ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
Animating with ViewPropertyAnimator
ViewPropertyAnimator提供了一种简单的方式来使用单个底层的Animator对象并行地对视图的多个属性进行动画化。 它的行为非常类似于ObjectAnimator,因为它会修改视图属性的实际值,但在一次动画化多个属性时效率比ObjectAnimatior更高。另外,使用ViewPropertyAnimator的代码更简洁易读。以下代码展示了使用多个 ObjectAnimator objects,单个ObjectAnimator,以及the ViewPropertyAnimator之间的差异当同时动画化视图的x和y属性。
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);
(编者按:简直简洁到爆有木有,下面是相关的源码)
/**
* This method returns a ViewPropertyAnimator object, which can be used to animate
* specific properties on this View.
*
* @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
*/
public ViewPropertyAnimator animate() {
if (mAnimator == null) {
mAnimator = new ViewPropertyAnimator(this);
}
return mAnimator;
}
/**
* This method will cause the View's x
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setX(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator x(float value) {
animateProperty(X, value);
return this;
}
/**
* This method will cause the View's y
property to be animated to the
* specified value. Animations already running on the property will be canceled.
*
* @param value The value to be animated to.
* @see View#setY(float)
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator y(float value) {
animateProperty(Y, value);
return this;
}
有关ViewPropertyAnimator的更多详细信息,请参阅相应的Android Developers博客文章。
Declaring Animations in XML
属性动画系统允许您使用XML声明属性动画,而不是以编程方式执行。 通过使用XML定义动画,您可以轻松地在多个活动中重新使用动画,并更轻松地编辑动画序列。
要区分使用新属性动画API的动画文件与使用旧版视图动画框架的动画文件,从Android 3.1开始,应将资源动画的XML文件保存在res / animator /目录中。
以下属性动画类使用以下XML标记支持XML声明:
- 1:ValueAnimator -
- 2:ObjectAnimator -
- 3:AnimatorSet -
要查找您可以在XML声明中使用的属性,请参阅Animation Resources 。以下示例顺序播放两组对象动画,第一个是两个一起播放的动画。
为了运行此动画,您必须将代码中的XML资源inflate到AnimatorSet对象,然后在开始动画集之前设置所有动画的目标对象。调用setTarget()为AnimatorSet的所有子项设置单个目标对象。 以下代码显示如何执行此操作:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
你还可以在XML中声明ValueAnimator,如以下示例所示:
要在你的代码中使用上面的ValueAnimator,你必须inflate 一个对象,添加AnimatorUpdateListener,获取更新的动画值,并将其用于其中一个视图的属性,如以下代码所示:
ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator updatedAnimation) {
float animatedValue = (float)updatedAnimation.getAnimatedValue();
textView.setTranslationX(animatedValue);
}
});
xmlAnimator.start();
有关ViewPropertyAnimator的更多详细信息,请参阅相应的Android Developers博客文章。
Implications for UI performance
更新UI的Animators 会为动画运行的每个帧带来额外的渲染工作。因此,使用资源密集型动画可能会对你的应用程序的性能产生负面影响。
为UI创建动画所需的工作被添加到渲染管道的动画阶段。你可以通过启用Profile GPU渲染和监视动画舞台来确定您的动画是否影响了您的应用的效果。 有关更多信息,请参阅Profile GPU Rendering Walkthrough。
我的csdn博客地址:http://blog.csdn.net/zcl1359205840?viewmode=contents