839 lines
39 KiB
Plaintext
839 lines
39 KiB
Plaintext
|
page.title=Animation
|
||
|
@jd:body
|
||
|
<div id="qv-wrapper">
|
||
|
<div id="qv">
|
||
|
<h2>In this document</h2>
|
||
|
|
||
|
<ol>
|
||
|
<li>
|
||
|
<a href="#property-animation">Property Animation</a>
|
||
|
|
||
|
<ol>
|
||
|
<li><a href="#value-animator">Animating with ValueAnimator</a></li>
|
||
|
|
||
|
<li><a href="#object-animator">Animating with ObjectAnimator</a></li>
|
||
|
|
||
|
<li><a href="#type-evaluator">Using the TypeEvaluator</a></li>
|
||
|
|
||
|
<li><a href="#interpolators">Using interpolators</a></li>
|
||
|
|
||
|
<li><a href="#keyframes">Specifying keyframes</a></li>
|
||
|
|
||
|
<li><a href="#choreography">Choreographing multiple animations with AnimatorSet</a></li>
|
||
|
|
||
|
<li><a href="#declaring-xml">Declaring animations in XML</a></li>
|
||
|
</ol>
|
||
|
</li>
|
||
|
|
||
|
<li>
|
||
|
<a href="#view-animation">View Animation</a>
|
||
|
|
||
|
<ol>
|
||
|
<li><a href="#tween-animation">Tween animation</a></li>
|
||
|
|
||
|
<li><a href="#frame-animation">Frame animation</a></li>
|
||
|
</ol>
|
||
|
</li>
|
||
|
</ol>
|
||
|
|
||
|
<h2>Key classes</h2>
|
||
|
|
||
|
<ol>
|
||
|
<li><code><a href=
|
||
|
"/reference/android/animation/ValueAnimator.html">ValueAnimator</a></code></li>
|
||
|
|
||
|
<li><code><a href=
|
||
|
"/reference/android/animation/ObjectAnimator.html">ObjectAnimator</a></code></li>
|
||
|
|
||
|
<li><code><a href=
|
||
|
"/reference/android/animation/TypeEvaluator.html">TypeEvaluator</a></code></li>
|
||
|
</ol>
|
||
|
|
||
|
<h2>Related samples</h2>
|
||
|
|
||
|
<ol>
|
||
|
<li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">API Demos</a></li>
|
||
|
</ol>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<p>The Android system provides a flexible animation system that allows you to animate
|
||
|
almost anything, either programmatically or declaratively with XML. There are two
|
||
|
animation systems that you can choose from: <a href="property-animation">property
|
||
|
animation</a> and <a href="#view-animation">view animation</a>. You can use whichever
|
||
|
system that matches your needs, but use only one system for each object that you
|
||
|
are animating.</p>
|
||
|
|
||
|
<h2 id="property-animation">Property Animation</h2>
|
||
|
|
||
|
<p>Introduced in Android 3.0, the property animation system allows you to animate
|
||
|
object properties of any type. <code>int</code>, <code>float</code>,
|
||
|
and hexadecimal color values are supported by default. You can animate any other type by telling the
|
||
|
system how to calculate the values for that given type.</p>
|
||
|
|
||
|
<p>The property animation system allows you to define many aspects of an animation,
|
||
|
such as:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>Duration</li>
|
||
|
|
||
|
<li>Repeat amount and behavior</li>
|
||
|
|
||
|
<li>Type of time interpolation</li>
|
||
|
|
||
|
<li>Animator sets to play animations together, sequentially, or after specified
|
||
|
delays</li>
|
||
|
|
||
|
<li>Frame refresh delay</li>
|
||
|
|
||
|
</ul>
|
||
|
|
||
|
<p>Most of the property animation system's features can be found in
|
||
|
{@link android.animation android.animation}. Because the
|
||
|
<a href="#view-animation>view animation</a> system already
|
||
|
defines many interpolators in {@link android.view.animation android.view.animation},
|
||
|
you will use those to define your animation's interpolation in the property animation
|
||
|
system as well.
|
||
|
</p>
|
||
|
|
||
|
<p>The following items are the main components of the property animation system:</p>
|
||
|
|
||
|
<dl>
|
||
|
<dt><strong>Animators</strong></dt>
|
||
|
|
||
|
<dd>
|
||
|
The {@link android.animation.Animator} class provides the basic structure for
|
||
|
creating animations. You normally do not use this class directly as it only provides
|
||
|
minimal functionality that must be extended to fully support animating values.
|
||
|
The following subclasses extend {@link android.animation.Animator}, which you might find more useful:
|
||
|
|
||
|
<ul>
|
||
|
<li>{@link android.animation.ValueAnimator} is the main timing engine for
|
||
|
property animation and computes the values for the property to be animated.
|
||
|
{@link android.animation.ValueAnimator} only computes the animation values and is
|
||
|
not aware of the specific object and property that is being animated or what the
|
||
|
values might be used for. You must listen for updates to values calculated by the
|
||
|
{@link android.animation.ValueAnimator} and process the data with your own logic.
|
||
|
See the section about <a href="#value-animator">Animating with ValueAnimator</a>
|
||
|
for more information.</li>
|
||
|
|
||
|
<li>{@link android.animation.ObjectAnimator} is a subclass of {@link
|
||
|
android.animation.ValueAnimator} and allows you to set a target object and object
|
||
|
property to animate. This class is aware of the object and property to be
|
||
|
animated, and updates the property accordingly when it computes a new value for
|
||
|
the animation. See the section about <a href="#object-animator">
|
||
|
Animating with ObjectAnimator</a> for more information.</li>
|
||
|
|
||
|
<li>{@link android.animation.AnimatorSet} provides a mechanism to group
|
||
|
animations together so that they are rendered in relation to one another. You can
|
||
|
set animations to play together, sequentially, or after a specified delay.
|
||
|
See the section about <a href="#choreography">
|
||
|
Choreographing multiple animations with Animator Sets</a> for more information.</li>
|
||
|
</ul>
|
||
|
</dd>
|
||
|
|
||
|
<dt><strong>Evaluators</strong></dt>
|
||
|
|
||
|
<dd>
|
||
|
<p>If you are animating an object property that is <em>not</em> an <code>int</code>,
|
||
|
<code>float</code>, or color, implement the {@link android.animation.TypeEvaluator}
|
||
|
interface to specify how to compute the object property's animated values. You give
|
||
|
a {@link android.animation.TypeEvaluator} the timing data that is provided by an
|
||
|
{@link android.animation.Animator} class, the animation's start and end value, and
|
||
|
provide logic that computes the animated values of the property based on this data.</p>
|
||
|
|
||
|
<p>You can also specify a custom {@link android.animation.TypeEvaluator} for
|
||
|
<code>int</code>, <code>float</code>, and color values as well, if you want to
|
||
|
process those types differently than the default behavior.</p>
|
||
|
|
||
|
<p>See <a href="#type-evaluator">Using a TypeEvaluator</a> for more information on
|
||
|
how to write a custom evaluator.</p>
|
||
|
</dd>
|
||
|
|
||
|
<dt><strong>Interpolators</strong></dt>
|
||
|
|
||
|
<dd>
|
||
|
<p>A time interpolator defines how specific values in an animation are calculated
|
||
|
as a function of time. For example, you can specify animations to happen linearly
|
||
|
across the whole animation, meaning the animation moves evenly the entire time, or
|
||
|
you can specify animations to use non-linear time, for example, using acceleration
|
||
|
or deceleration at the beginning or end of the animation.</p>
|
||
|
|
||
|
<p>The Android system provides a set of common interpolators in
|
||
|
{@link android.view.animation android.view.animation}. If none of these suits your needs, you
|
||
|
can implement the {@link android.animation.TimeInterpolator} interface and create
|
||
|
your own. See <a href="#interpolators">Interpolators</a> for more information on
|
||
|
how to write a custom interpolator.</p>
|
||
|
</dd>
|
||
|
</dl>
|
||
|
|
||
|
|
||
|
<p>The <code>com.example.android.apis.animation</code> package in the <a href=
|
||
|
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/index.html">
|
||
|
API Demos</a> sample project also provides a good overview and many examples on how to
|
||
|
use the property animation system.</p>
|
||
|
|
||
|
|
||
|
<h3>How the property animation system calculates animated values</h3>
|
||
|
|
||
|
<p>When you call {@link android.animation.ValueAnimator#start start()} to begin an animation,
|
||
|
the {@link android.animation.ValueAnimator} calculates
|
||
|
an <em>elapsed fraction</em> between 0 and 1, based on the duration of the animation
|
||
|
and how much time has elapsed. The elapsed fraction represents the percentage of time
|
||
|
that the animation has completed, 0 meaning 0% and 1 meaning 100%. The Animator then
|
||
|
calls the {@link android.animation.TimeInterpolator} that is currently set,
|
||
|
to calculate an <em>eased fraction</em>,
|
||
|
which is a modified value of the elapsed fraction that takes into account the interpolator that
|
||
|
is set (time interpolation is often referred to as <em>easing</em>). The eased fraction
|
||
|
is the final value that is used to animate the property.</p>
|
||
|
|
||
|
<p>Once the eased fraction is calculated, {@link android.animation.ValueAnimator} calls
|
||
|
the appropriate {@link android.animation.TypeEvaluator} to calculate the final value of
|
||
|
the property that you are animating, based on the eased fraction, the starting value,
|
||
|
and ending value of the animation.</p>
|
||
|
|
||
|
<h3 id="value-animator">Animating with ValueAnimator</h3>
|
||
|
|
||
|
<p>The {@link android.animation.ValueAnimator} class lets you animate values of some
|
||
|
type for the duration of an animation by specifying a set of <code>int</code>,
|
||
|
<code>float</code>, or color values to animate over and the duration of the animation.
|
||
|
You obtain a {@link android.animation.ValueAnimator} by calling one of its factory
|
||
|
methods: {@link android.animation.ValueAnimator#ofInt ofInt()},
|
||
|
{@link android.animation.ValueAnimator#ofFloat ofFloat()},
|
||
|
or {@link android.animation.ValueAnimator#ofObject ofObject()}. For example:</p>
|
||
|
|
||
|
<pre>ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);
|
||
|
animation.setDuration(1000);
|
||
|
animation.start();
|
||
|
</pre>
|
||
|
|
||
|
<p>In this code, the {@link android.animation.ValueAnimator} starts
|
||
|
calculating the values of the animation, between 0 and 1, for
|
||
|
a duration of 1000 ms, when the <code>start()</code> method runs.</p>
|
||
|
|
||
|
<p>You can also specify a custom type to animate by doing the following:</p>
|
||
|
|
||
|
<pre>ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
|
||
|
animation.setDuration(1000);
|
||
|
animation.start();
|
||
|
</pre>
|
||
|
|
||
|
<p>In this code, the {@link android.animation.ValueAnimator} starts
|
||
|
calculating the values of the animation, between <code>startPropertyValue</code> and
|
||
|
<code>endPropertyValue</code> using the logic supplied by <code>MyTypeEvaluator</code>
|
||
|
for a duration of 1000 ms, when the {@link android.animation.ValueAnimator#start start()}
|
||
|
method runs.</p>
|
||
|
|
||
|
<p>The previous code snippets, however, do not affect an object, because the {@link
|
||
|
android.animation.ValueAnimator} does not operate on objects or properties directly. To
|
||
|
use the results of a {@link android.animation.ValueAnimator}, you must define listeners
|
||
|
in the {@link android.animation.ValueAnimator} to appropriately handle important events
|
||
|
during the animation's lifespan, such as frame updates. You can implement the following
|
||
|
interfaces to create listeners for {@link android.animation.ValueAnimator}:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>{@link android.animation.Animator.AnimatorListener}
|
||
|
|
||
|
<ul>
|
||
|
<li>{@link android.animation.Animator.AnimatorListener#onAnimationStart
|
||
|
onAnimationStart()} - Called when the animation starts</li>
|
||
|
|
||
|
<li>{@link android.animation.Animator.AnimatorListener#onAnimationEnd
|
||
|
onAnimationEnd()} - Called when the animation ends.</li>
|
||
|
|
||
|
<li>{@link android.animation.Animator.AnimatorListener#onAnimationRepeat
|
||
|
onAnimationRepeat()} - Called when the animation repeats itself.</li>
|
||
|
|
||
|
<li>{@link android.animation.Animator.AnimatorListener#onAnimationCancel
|
||
|
onAnimationCancel()} - Called when the animation is canceled.</li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
|
||
|
<li>{@link android.animation.ValueAnimator.AnimatorUpdateListener}
|
||
|
|
||
|
<ul>
|
||
|
<li>
|
||
|
<p>{@link
|
||
|
android.animation.ValueAnimator.AnimatorUpdateListener#onAnimationUpdate
|
||
|
onAnimationUpdate()} - called on every frame of the animation.
|
||
|
Listen to this event to use the calculated values generated by
|
||
|
{@link android.animation.ValueAnimator} during an animation. To use the value,
|
||
|
query the {@link android.animation.ValueAnimator} object passed into the event
|
||
|
to get the current animated value with the
|
||
|
{@link android.animation.ValueAnimator#getAnimatedValue getAnimatedValue()} method.</p>
|
||
|
|
||
|
<p>If you are animating your own custom object (not View objects), this
|
||
|
callback must also call the {@link android.view.View#invalidate invalidate()}
|
||
|
method to force a redraw of the screen. If you are animating View objects,
|
||
|
{@link android.view.View#invalidate invalidate()} is automatically called when
|
||
|
a property of the View is changed.</p>
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>You can extend the {@link android.animation.AnimatorListenerAdapter} class
|
||
|
instead of implementing the {@link android.animation.Animator.AnimatorListener}
|
||
|
interface, if you do not want to implement all of the methods of the {@link
|
||
|
android.animation.Animator.AnimatorListener} interface. The {@link
|
||
|
android.animation.AnimatorListenerAdapter} class provides empty implementations of the
|
||
|
methods that you can choose to override.</p>
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
<p>For example, the <a href=
|
||
|
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
|
||
|
Bouncing Balls</a> sample in the API demos creates an {@link
|
||
|
android.animation.AnimatorListenerAdapter} for just the {@link
|
||
|
android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
|
||
|
callback:</p>
|
||
|
<pre>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());
|
||
|
}
|
||
|
|
||
|
</pre>
|
||
|
|
||
|
<h3 id="object-animator">Animating with ObjectAnimator</h3>
|
||
|
|
||
|
<p>The {@link android.animation.ObjectAnimator} is a subclass of the {@link
|
||
|
android.animation.ValueAnimator} (discussed in the previous section)
|
||
|
and combines the timing engine and value computation
|
||
|
of {@link android.animation.ValueAnimator} with the ability to animate a named property
|
||
|
of a target object. This makes animating any object much easier, as you no longer need
|
||
|
to implement the {@link android.animation.ValueAnimator.AnimatorUpdateListener}, because
|
||
|
the animated property updates automatically.</p>
|
||
|
|
||
|
<p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
|
||
|
android.animation.ValueAnimator}, but you also specify the object and that object's
|
||
|
property (as a String) that you want to animate:</p>
|
||
|
<pre>
|
||
|
ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
|
||
|
anim.setDuration(1000);
|
||
|
anim.start();
|
||
|
</pre>
|
||
|
|
||
|
<p>To have the {@link android.animation.ObjectAnimator} update properties correctly,
|
||
|
you must do the following:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>The object property that you are animating must have a setter function in the
|
||
|
form of <code>set<propertyName>()</code>. Because the {@link
|
||
|
android.animation.ObjectAnimator} automatically updates the property during
|
||
|
animation, it must be able to access the property with this setter method. For
|
||
|
example, if the property name is <code>foo</code>, you need to have a
|
||
|
<code>setFoo()</code> method. If this setter method does not exist, you have three
|
||
|
options:
|
||
|
|
||
|
<ul>
|
||
|
<li>Add the setter method to the class if you have the rights to do so.</li>
|
||
|
|
||
|
<li>Use a wrapper class that you have rights to change and have that wrapper
|
||
|
receive the value with a valid setter method and forward it to the original
|
||
|
object.</li>
|
||
|
|
||
|
<li>Use {@link android.animation.ValueAnimator} instead.</li>
|
||
|
</ul>
|
||
|
</li>
|
||
|
|
||
|
<li>If you specify only one value for the <code>values...</code> parameter,
|
||
|
in one of the {@link android.animation.ObjectAnimator} factory methods, it is assumed to be
|
||
|
the ending value of the animation. Therefore, the object property that you are
|
||
|
animating must have a getter function that is used to obtain the starting value of
|
||
|
the animation. The getter function must be in the form of
|
||
|
<code>get<propertyName>()</code>. For example, if the property name is
|
||
|
<code>foo</code>, you need to have a <code>getFoo()</code> method.</li>
|
||
|
|
||
|
<li>The getter (if needed) and setter methods of the property that you are animating must
|
||
|
return the same type as the starting and ending values that you specify to {@link
|
||
|
android.animation.ObjectAnimator}. For example, you must have
|
||
|
<code>targetObject.setPropName(float)</code> and
|
||
|
<code>targetObject.getPropName(float)</code> if you construct the following {@link
|
||
|
android.animation.ObjectAnimator}:
|
||
|
<pre>ObjectAnimator.ofFloat(targetObject, "propName", 1f)</pre>
|
||
|
</li>
|
||
|
</ul>
|
||
|
|
||
|
<h3 id="type-evaluator">Using the TypeEvaluator</h3>
|
||
|
|
||
|
<p>If you want to animate a type that is unknown to the Android system,
|
||
|
you can create your own evaluator by implementing the {@link
|
||
|
android.animation.TypeEvaluator} interface. The types that are known by the Android
|
||
|
system are <code>int</code>, <code>float</code>, or a color, which are supported by the
|
||
|
{@link android.animation.IntEvaluator}, {@link android.animation.FloatEvaluator}, and
|
||
|
{@link android.animation.ArgbEvaluator} type evaluators.</p>
|
||
|
|
||
|
<p>There is only one method to implement in the {@link android.animation.TypeEvaluator}
|
||
|
interface, the {@link android.animation.TypeEvaluator#evaluate evaluate()} method.
|
||
|
This allows the animator that you are using to return an
|
||
|
appropriate value for your animated property at the current point of the animation. The
|
||
|
{@link android.animation.FloatEvaluator} class demonstrates how to do this:</p>
|
||
|
<pre>
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
</pre>
|
||
|
|
||
|
<p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or
|
||
|
{@link android.animation.ObjectAnimator}) runs, it calculates a current elapsed
|
||
|
fraction of the animation (a value between 0 and 1) and then calculates an eased
|
||
|
version of that depending on what interpolator that you are using. The eased fraction
|
||
|
is what your {@link android.animation.TypeEvaluator} receives through the <code>fraction</code>
|
||
|
parameter, so you do not have to take into account the interpolator
|
||
|
when calculating animated values.</p>
|
||
|
|
||
|
<h3 id="interpolators">Using Interpolators</h3>
|
||
|
|
||
|
<p>An interpolator define how specific values in an animation are
|
||
|
calculated as a function of time. For example, you can specify animations to happen
|
||
|
linearly across the whole animation, meaning the animation moves evenly the entire
|
||
|
time, or you can specify animations to use non-linear time, for example, using
|
||
|
acceleration or deceleration at the beginning or end of the animation.</p>
|
||
|
|
||
|
<p>Interpolators in the animation system receive a fraction from Animators that represent the elapsed time
|
||
|
of the animation. Interpolators modify this fraction to coincide with the type of
|
||
|
animation that it aims to provide. The Android system provides a set of common
|
||
|
interpolators in the {@link android.view.animation android.view.animation package}. If
|
||
|
none of these suit your needs, you can implement the {@link
|
||
|
android.animation.TimeInterpolator} interface and create your own.</p>
|
||
|
|
||
|
<p>As an example, how the default interpolator {@link
|
||
|
android.view.animation.AccelerateDecelerateInterpolator} and the {@link
|
||
|
android.view.animation.LinearInterpolator} calculate eased fractions are compared below. The {@link
|
||
|
android.view.animation.LinearInterpolator} has no effect on the elapsed fraction,
|
||
|
because a linear interpolation is calculated the same way as the elapsed fraction. The
|
||
|
{@link android.view.animation.AccelerateDecelerateInterpolator} accelerates into the
|
||
|
animation and decelerates out of it. The following methods define the logic for these
|
||
|
interpolators:</p>
|
||
|
|
||
|
<p><strong>AccelerateDecelerateInterpolator</strong></p>
|
||
|
<pre>public float getInterpolation(float input) {
|
||
|
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
|
||
|
}</pre>
|
||
|
|
||
|
<p><strong>LinearInterpolator</strong></p>
|
||
|
<pre>public float getInterpolation(float input) {
|
||
|
return input;
|
||
|
}</pre>
|
||
|
|
||
|
<p>The following table represents the approximate values that are calculated by these
|
||
|
interpolators for an animation that lasts 1000ms:</p>
|
||
|
|
||
|
<table>
|
||
|
<tr>
|
||
|
<th>ms elapsed</th>
|
||
|
|
||
|
<th>Elapsed fraction/Eased fraction (Linear)</th>
|
||
|
|
||
|
<th>Eased fraction (Accelerate/Decelerate)</th>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>0</td>
|
||
|
|
||
|
<td>0</td>
|
||
|
|
||
|
<td>0</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>200</td>
|
||
|
|
||
|
<td>.2</td>
|
||
|
|
||
|
<td>.1</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>400</td>
|
||
|
|
||
|
<td>.4</td>
|
||
|
|
||
|
<td>.345</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>600</td>
|
||
|
|
||
|
<td>.6</td>
|
||
|
|
||
|
<td>.8</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>800</td>
|
||
|
|
||
|
<td>.8</td>
|
||
|
|
||
|
<td>.9</td>
|
||
|
</tr>
|
||
|
|
||
|
<tr>
|
||
|
<td>1000</td>
|
||
|
|
||
|
<td>1</td>
|
||
|
|
||
|
<td>1</td>
|
||
|
</tr>
|
||
|
</table>
|
||
|
|
||
|
<p>As the table shows, the {@link android.view.animation.LinearInterpolator} changes
|
||
|
the values at the same speed, .2 for every 200ms that passes. The {@link
|
||
|
android.view.animation.AccelerateDecelerateInterpolator} changes the values faster than
|
||
|
{@link android.view.animation.LinearInterpolator} between 200ms and 600ms and slower
|
||
|
between 600ms and 1000ms.</p>
|
||
|
|
||
|
<h3 id="keyframes">Specifying Keyframes</h3>
|
||
|
|
||
|
<p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets
|
||
|
you define a specific state at a specific time of an animation. Each keyframe can also
|
||
|
have its own interpolator to control the behavior of the animation in the interval
|
||
|
between the previous keyframe's time and the time of this keyframe.</p>
|
||
|
|
||
|
<p>To instantiate a {@link android.animation.Keyframe} object, you must use one of the
|
||
|
factory methods, {@link android.animation.Keyframe#ofInt ofInt()}, {@link
|
||
|
android.animation.Keyframe#ofFloat ofFloat()}, or {@link
|
||
|
android.animation.Keyframe#ofObject ofObject()} to obtain the appropriate type of
|
||
|
{@link android.animation.Keyframe}. You then call the {@link
|
||
|
android.animation.PropertyValuesHolder#ofKeyframe ofKeyframe()} factory method to
|
||
|
obtain a {@link android.animation.PropertyValuesHolder} object. Once you have the
|
||
|
object, you can obtain an animator by passing in the {@link
|
||
|
android.animation.PropertyValuesHolder} object and the object to animate. The following
|
||
|
code snippet demonstrates how to do this:</p>
|
||
|
<pre>
|
||
|
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
|
||
|
Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
|
||
|
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
|
||
|
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
|
||
|
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
|
||
|
rotationAnim.setDuration(5000ms);
|
||
|
|
||
|
</pre>For a more complete example on how to use keyframes, see the <a href=
|
||
|
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
|
||
|
MultiPropertyAnimation</a> sample in APIDemos.
|
||
|
|
||
|
<h3 id="choreography">Choreographing multiple animations with Animator Sets</h3>
|
||
|
|
||
|
<p>In many cases, you want to play an animation that depends on when another animation
|
||
|
starts or finishes. The Android system lets you bundle animations together into an
|
||
|
{@link android.animation.AnimatorSet}, so that you can specify whether to start animations
|
||
|
simultaneously, sequentially, or after a specified delay. You can also nest {@link
|
||
|
android.animation.AnimatorSet} objects within each other.</p>
|
||
|
|
||
|
<p>The following sample code taken from the <a href=
|
||
|
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
|
||
|
Bouncing Balls</a> sample (modified for simplicity) plays the following
|
||
|
{@link android.animation.Animator} objects in the following manner:</p>
|
||
|
|
||
|
<ol>
|
||
|
<li>Plays <code>bounceAnim</code>.</li>
|
||
|
|
||
|
<li>Plays <code>squashAnim1</code>, <code>squashAnim2</code>,
|
||
|
<code>stretchAnim1</code>, and <code>stretchAnim2</code> at the same time.</li>
|
||
|
|
||
|
<li>Plays <code>bounceBackAnim</code>.</li>
|
||
|
|
||
|
<li>Plays <code>fadeAnim</code>.</li>
|
||
|
</ol>
|
||
|
<pre>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();
|
||
|
</pre>
|
||
|
|
||
|
<p>For a more complete example on how to use animator sets, see the <a href=
|
||
|
"{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/BouncingBalls.html">
|
||
|
Bouncing Balls</a> sample in APIDemos.</p>
|
||
|
|
||
|
<h3 id="declaring-xml">Declaring animations in XML</h3>
|
||
|
|
||
|
<p>As with <a href="view-animation">view animation</a>, you can declare property animations with
|
||
|
XML instead of doing it programmatically. The following Android classes also have XML
|
||
|
declaration support with the following XML tags:</p>
|
||
|
|
||
|
<ul>
|
||
|
<li>{@link android.animation.ValueAnimator} - <code><animator></code></li>
|
||
|
|
||
|
<li>{@link android.animation.ObjectAnimator} - <code><objectAnimator></code></li>
|
||
|
|
||
|
<li>{@link android.animation.AnimatorSet} - <code><AnimatorSet></code></li>
|
||
|
</ul>
|
||
|
|
||
|
<p>Both <code><animator></code> ({@link android.animation.ValueAnimator}) and
|
||
|
<code><objectAnimator></code> ({@link android.animation.ObjectAnimator}) have the
|
||
|
following attributes:</p>
|
||
|
|
||
|
<dl>
|
||
|
<dt><code>android:duration</code></dt>
|
||
|
<dd>The number of milliseconds that the animation runs.</dd>
|
||
|
|
||
|
<dt><code>android:valueFrom</code> and <code>android:valueTo</code></dt>
|
||
|
<dd>The values being animated
|
||
|
between. These are restricted to numbers (<code>float</code> or <code>int</code>) in
|
||
|
XML. They can be <code>float</code>, <code>int</code>, or any kind of
|
||
|
<code>Object</code> when creating animations programmatically.</dd>
|
||
|
|
||
|
<dt><code>android:valueType</code></dt>
|
||
|
<dd>Set to either <code>"floatType"</code> or <code>"intType"</code>.</dd>
|
||
|
|
||
|
<dt><code>android:startDelay</code></dt>
|
||
|
<dd>The delay, in milliseconds, before the animation begins
|
||
|
playing (after calling {@link android.animation.ValueAnimator#start start()}).</dd>
|
||
|
|
||
|
<dt><code>android:repeatCount</code></dt>
|
||
|
<dd>How many times to repeat an animation. Set to
|
||
|
<code>"-1"</code> for infinite repeating or to a positive integer. For example, a value of
|
||
|
<code>"1"</code> means that the animation is repeated once after the initial run of the
|
||
|
animation, so the animation plays a total of two times. The default value is
|
||
|
<code>"0"</code>.</dd>
|
||
|
|
||
|
<dt><code>android:repeatMode</code></dt>
|
||
|
<dd>How an animation behaves when it reaches the end of the
|
||
|
animation. <code>android:repeatCount</code> must be set to a positive integer or
|
||
|
<code>"-1"</code> for this attribute to have an effect. Set to <code>"reverse"</code> to
|
||
|
have the animation reverse direction with each iteration or <code>"repeat"</code> to
|
||
|
have the animation loop from the beginning each time.</dd>
|
||
|
</dl>
|
||
|
|
||
|
<p>The <code>objectAnimator</code> ({@link android.animation.ObjectAnimator}) element has the
|
||
|
additional attribute <code>propertyName</code>, that lets you specify the name of the
|
||
|
property being animated. The <code>objectAnimator</code> element does not expose a
|
||
|
<code>target</code> attribute, however, so you cannot set the object to animate in the
|
||
|
XML declaration. You have to inflate the XML resource by calling
|
||
|
{@link android.animation.AnimatorInflater#loadAnimator loadAnimator()} and call
|
||
|
{@link android.animation.ObjectAnimator#setTarget setTarget()} to set the target object, before calling
|
||
|
{@link android.animation.ObjectAnimator#start start()}.</p>
|
||
|
|
||
|
<p>The <code>set</code> element ({@link android.animation.AnimatorSet}) exposes a single
|
||
|
attribute, <code>ordering</code>. Set this attribute to <code>together</code> (default)
|
||
|
to play all the animations in this set at once. Set this attribute to
|
||
|
<code>sequentially</code> to play the animations in the order they are declared.</p>
|
||
|
|
||
|
<p>You can specify nested <code>set</code> tags to further group animations together.
|
||
|
The animations that you want to group together should be children of the
|
||
|
<code>set</code> tag and can define their own <code>ordering</code> attribute.</p>
|
||
|
|
||
|
<p>As an example, this XML code creates an {@link android.animation.AnimatorSet} object
|
||
|
that animates x and y at the same time (<code>together</code> is the default ordering
|
||
|
when nothing is specified), then runs an animation that fades an object out:</p>
|
||
|
<pre><set android:ordering="sequentially">
|
||
|
<set>
|
||
|
<objectAnimator
|
||
|
android:propertyName="x"
|
||
|
android:duration="500"
|
||
|
android:valueTo="400"
|
||
|
android:valueType="int"/>
|
||
|
<objectAnimator
|
||
|
android:propertyName="y"
|
||
|
android:duration="500"
|
||
|
android:valueTo="300"
|
||
|
android:valueType="int" >
|
||
|
</set>
|
||
|
<objectAnimator
|
||
|
android:propertyName="alpha"
|
||
|
android:duration="500"
|
||
|
android:valueTo="0f"/>
|
||
|
</set>
|
||
|
</pre>
|
||
|
|
||
|
<p>In order to run this animation, you must inflate the XML resources in your code to
|
||
|
an {@link android.animation.AnimatorSet} object, and then set the target objects for all of
|
||
|
the animations before starting the animation set. Calling {@link
|
||
|
android.animation.AnimatorSet#setTarget setTarget()} sets a single target object for
|
||
|
all children of the {@link android.animation.AnimatorSet}.</p>
|
||
|
|
||
|
<h2 id="view-animation">View Animation</h2>You can use View Animation in any View
|
||
|
object to perform tweened animation and frame by frame animation. Tween animation
|
||
|
calculates the animation given information such as the start point, end point, size,
|
||
|
rotation, and other common aspects of an animation. Frame by frame animation lets you
|
||
|
load a series of Drawable resources one after another to create an animation.
|
||
|
|
||
|
<h3 id="tween-animation">Tween Animation</h3>
|
||
|
|
||
|
<p>A tween animation can perform a series of simple transformations (position, size,
|
||
|
rotation, and transparency) on the contents of a View object. So, if you have a
|
||
|
{@link android.widget.TextView} object, you can move, rotate, grow, or shrink the text. If it has a background
|
||
|
image, the background image will be transformed along with the text. The {@link
|
||
|
android.view.animation animation package} provides all the classes used in a tween
|
||
|
animation.</p>
|
||
|
|
||
|
<p>A sequence of animation instructions defines the tween animation, defined by either
|
||
|
XML or Android code. As with defining a layout, an XML file is recommended because it's
|
||
|
more readable, reusable, and swappable than hard-coding the animation. In the example
|
||
|
below, we use XML. (To learn more about defining an animation in your application code,
|
||
|
instead of XML, refer to the {@link android.view.animation.AnimationSet} class and
|
||
|
other {@link android.view.animation.Animation} subclasses.)</p>
|
||
|
|
||
|
<p>The animation instructions define the transformations that you want to occur, when
|
||
|
they will occur, and how long they should take to apply. Transformations can be
|
||
|
sequential or simultaneous — for example, you can have the contents of a TextView
|
||
|
move from left to right, and then rotate 180 degrees, or you can have the text move and
|
||
|
rotate simultaneously. Each transformation takes a set of parameters specific for that
|
||
|
transformation (starting size and ending size for size change, starting angle and
|
||
|
ending angle for rotation, and so on), and also a set of common parameters (for
|
||
|
instance, start time and duration). To make several transformations happen
|
||
|
simultaneously, give them the same start time; to make them sequential, calculate the
|
||
|
start time plus the duration of the preceding transformation.</p>
|
||
|
|
||
|
<p>The animation XML file belongs in the <code>res/anim/</code> directory of your
|
||
|
Android project. The file must have a single root element: this will be either a single
|
||
|
<code><alpha></code>, <code><scale></code>, <code><translate></code>,
|
||
|
<code><rotate></code>, interpolator element, or <code><set></code> element
|
||
|
that holds groups of these elements (which may include another
|
||
|
<code><set></code>). By default, all animation instructions are applied
|
||
|
simultaneously. To make them occur sequentially, you must specify the
|
||
|
<code>startOffset</code> attribute, as shown in the example below.</p>
|
||
|
|
||
|
<p>The following XML from one of the ApiDemos is used to stretch, then simultaneously
|
||
|
spin and rotate a View object.</p>
|
||
|
<pre>
|
||
|
<set android:shareInterpolator="false">
|
||
|
<scale
|
||
|
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
|
||
|
android:fromXScale="1.0"
|
||
|
android:toXScale="1.4"
|
||
|
android:fromYScale="1.0"
|
||
|
android:toYScale="0.6"
|
||
|
android:pivotX="50%"
|
||
|
android:pivotY="50%"
|
||
|
android:fillAfter="false"
|
||
|
android:duration="700" />
|
||
|
<set android:interpolator="@android:anim/decelerate_interpolator">
|
||
|
<scale
|
||
|
android:fromXScale="1.4"
|
||
|
android:toXScale="0.0"
|
||
|
android:fromYScale="0.6"
|
||
|
android:toYScale="0.0"
|
||
|
android:pivotX="50%"
|
||
|
android:pivotY="50%"
|
||
|
android:startOffset="700"
|
||
|
android:duration="400"
|
||
|
android:fillBefore="false" />
|
||
|
<rotate
|
||
|
android:fromDegrees="0"
|
||
|
android:toDegrees="-45"
|
||
|
android:toYScale="0.0"
|
||
|
android:pivotX="50%"
|
||
|
android:pivotY="50%"
|
||
|
android:startOffset="700"
|
||
|
android:duration="400" />
|
||
|
</set>
|
||
|
</set>
|
||
|
</pre>
|
||
|
|
||
|
<p>Screen coordinates (not used in this example) are (0,0) at the upper left hand
|
||
|
corner, and increase as you go down and to the right.</p>
|
||
|
|
||
|
<p>Some values, such as pivotX, can be specified relative to the object itself or
|
||
|
relative to the parent. Be sure to use the proper format for what you want ("50" for
|
||
|
50% relative to the parent, or "50%" for 50% relative to itself).</p>
|
||
|
|
||
|
<p>You can determine how a transformation is applied over time by assigning an {@link
|
||
|
android.view.animation.Interpolator}. Android includes several Interpolator subclasses
|
||
|
that specify various speed curves: for instance, {@link
|
||
|
android.view.animation.AccelerateInterpolator} tells a transformation to start slow and
|
||
|
speed up. Each one has an attribute value that can be applied in the XML.</p>
|
||
|
|
||
|
<p>With this XML saved as <code>hyperspace_jump.xml</code> in the
|
||
|
<code>res/anim/</code> directory of the project, the following code will reference
|
||
|
it and apply it to an {@link android.widget.ImageView} object from the layout.</p>
|
||
|
<pre>
|
||
|
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
|
||
|
Animation hyperspaceJumpAnimation = AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
|
||
|
spaceshipImage.startAnimation(hyperspaceJumpAnimation);
|
||
|
</pre>
|
||
|
|
||
|
<p>As an alternative to <code>startAnimation()</code>, you can define a starting time
|
||
|
for the animation with <code>{@link android.view.animation.Animation#setStartTime(long)
|
||
|
Animation.setStartTime()}</code>, then assign the animation to the View with
|
||
|
<code>{@link android.view.View#setAnimation(android.view.animation.Animation)
|
||
|
View.setAnimation()}</code>.</p>
|
||
|
|
||
|
<p>For more information on the XML syntax, available tags and attributes, see <a href=
|
||
|
"{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
|
||
|
|
||
|
<p class="note"><strong>Note:</strong> Regardless of how your animation may move or
|
||
|
resize, the bounds of the View that holds your animation will not automatically adjust
|
||
|
to accommodate it. Even so, the animation will still be drawn beyond the bounds of its
|
||
|
View and will not be clipped. However, clipping <em>will occur</em> if the animation
|
||
|
exceeds the bounds of the parent View.</p>
|
||
|
|
||
|
<h3 id="frame-animation">Frame Animation</h3>
|
||
|
|
||
|
<p>This is a traditional animation in the sense that it is created with a sequence of
|
||
|
different images, played in order, like a roll of film. The {@link
|
||
|
android.graphics.drawable.AnimationDrawable} class is the basis for frame
|
||
|
animations.</p>
|
||
|
|
||
|
<p>While you can define the frames of an animation in your code, using the {@link
|
||
|
android.graphics.drawable.AnimationDrawable} class API, it's more simply accomplished
|
||
|
with a single XML file that lists the frames that compose the animation. Like the tween
|
||
|
animation above, the XML file for this kind of animation belongs in the
|
||
|
<code>res/drawable/</code> directory of your Android project. In this case, the
|
||
|
instructions are the order and duration for each frame of the animation.</p>
|
||
|
|
||
|
<p>The XML file consists of an <code><animation-list></code> element as the root
|
||
|
node and a series of child <code><item></code> nodes that each define a frame: a
|
||
|
drawable resource for the frame and the frame duration. Here's an example XML file for
|
||
|
a frame-by-frame animation:</p>
|
||
|
<pre>
|
||
|
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
|
||
|
android:oneshot="true">
|
||
|
<item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
|
||
|
<item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
|
||
|
<item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
|
||
|
</animation-list>
|
||
|
</pre>
|
||
|
|
||
|
<p>This animation runs for just three frames. By setting the
|
||
|
<code>android:oneshot</code> attribute of the list to <var>true</var>, it will cycle
|
||
|
just once then stop and hold on the last frame. If it is set <var>false</var> then the
|
||
|
animation will loop. With this XML saved as <code>rocket_thrust.xml</code> in the
|
||
|
<code>res/drawable/</code> directory of the project, it can be added as the background
|
||
|
image to a View and then called to play. Here's an example Activity, in which the
|
||
|
animation is added to an {@link android.widget.ImageView} and then animated when the
|
||
|
screen is touched:</p>
|
||
|
<pre>
|
||
|
AnimationDrawable rocketAnimation;
|
||
|
|
||
|
public void onCreate(Bundle savedInstanceState) {
|
||
|
super.onCreate(savedInstanceState);
|
||
|
setContentView(R.layout.main);
|
||
|
|
||
|
ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
|
||
|
rocketImage.setBackgroundResource(R.drawable.rocket_thrust);
|
||
|
rocketAnimation = (AnimationDrawable) rocketImage.getBackground();
|
||
|
}
|
||
|
|
||
|
public boolean onTouchEvent(MotionEvent event) {
|
||
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||
|
rocketAnimation.start();
|
||
|
return true;
|
||
|
}
|
||
|
return super.onTouchEvent(event);
|
||
|
}
|
||
|
</pre>
|
||
|
|
||
|
<p>It's important to note that the <code>start()</code> method called on the
|
||
|
AnimationDrawable cannot be called during the <code>onCreate()</code> method of your
|
||
|
Activity, because the AnimationDrawable is not yet fully attached to the window. If you
|
||
|
want to play the animation immediately, without requiring interaction, then you might
|
||
|
want to call it from the <code>{@link
|
||
|
android.app.Activity#onWindowFocusChanged(boolean) onWindowFocusChanged()}</code>
|
||
|
method in your Activity, which will get called when Android brings your window into
|
||
|
focus.</p>
|
||
|
|
||
|
<p>For more information on the XML syntax, available tags and attributes, see <a href=
|
||
|
"{@docRoot}guide/topics/resources/animation-resource.html">Animation Resources</a>.</p>
|