The property animation system is a robust framework that allows you to animate almost anything.
>The ValueAnimator
class lets you animate values of some type for the duration of an animation by specifying a set of int
, float
, or color values to animate through. You obtain a ValueAnimator
by calling one of its factory methods: ofInt()
, ofFloat()
, or ofObject()
. For example:
ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f); animation.setDuration(1000); animation.start();
> Instantiating an ObjectAnimator
is similar to a ValueAnimator
, but you also specify the object and the name of that object's property (as a String) along with the values to animate between:
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f); anim.setDuration(1000); anim.start();The Android system lets you bundle animations together into an
AnimatorSet
, so that you can specify whether to start animations simultaneously, sequentially, or after a specified delay. You can also nest
AnimatorSet
objects within each other.
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();> For example, the Bouncing Balls sample in the API demos creates an
AnimatorListenerAdapter
for just the
onAnimationEnd()
callback:
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()); }
If you want to animate a type that is unknown to the Android system, you can create your own evaluator by implementing the TypeEvaluator
interface. The types that are known by the Android system are int
, float
, or a color, which are supported by the IntEvaluator
, FloatEvaluator
, and ArgbEvaluator
type evaluators.
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); } }> 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();
> The following example plays the two sets of object animations sequentially, with the first nested set playing two object animations together:
<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>
In order to run this animation, you must inflate the XML resources in your code to an AnimatorSet
object, and then set the target objects for all of the animations before starting the animation set. Calling setTarget()
sets a single target object for all children of the AnimatorSet
as a convenience. The following code shows how to do this:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext, R.anim.property_animator); set.setTarget(myObject); set.start();