summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/graphics/animation.jd
blob: 83a4e1d30662c22eaca063e4b45e048241321d2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
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 a 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">Using 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&lt;propertyName&gt;()</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&lt;propertyName&gt;()</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 a 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>
<p>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.</p>

  <h3 id="choreography">Choreographing multiple animations with AnimatorSet</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>&lt;animator&gt;</code></li>

    <li>{@link android.animation.ObjectAnimator} - <code>&lt;objectAnimator&gt;</code></li>

    <li>{@link android.animation.AnimatorSet} - <code>&lt;AnimatorSet&gt;</code></li>
  </ul>

  <p>Both <code>&lt;animator&gt;</code> ({@link android.animation.ValueAnimator}) and
  <code>&lt;objectAnimator&gt;</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>&lt;set android:ordering="sequentially"&gt;
    &lt;set&gt;
        &lt;objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="int"/&gt;
        &lt;objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="int"/&gt;
    &lt;/set&gt;
    &lt;objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="0f"/&gt;
&lt;/set&gt;</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 &mdash; 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>&lt;alpha&gt;</code>, <code>&lt;scale&gt;</code>, <code>&lt;translate&gt;</code>,
  <code>&lt;rotate&gt;</code>, interpolator element, or <code>&lt;set&gt;</code> element
  that holds groups of these elements (which may include another
  <code>&lt;set&gt;</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>&lt;set android:shareInterpolator="false"&gt;
    &lt;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" /&gt;
    &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
        &lt;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" /&gt;
        &lt;rotate
           android:fromDegrees="0"
           android:toDegrees="-45"
           android:toYScale="0.0"
           android:pivotX="50%"
           android:pivotY="50%"
           android:startOffset="700"
           android:duration="400" /&gt;
    &lt;/set&gt;
&lt;/set&gt;</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>&lt;animation-list&gt;</code> element as the root
  node and a series of child <code>&lt;item&gt;</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>
&lt;animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"&gt;
    &lt;item android:drawable="@drawable/rocket_thrust1" android:duration="200" /&gt;
    &lt;item android:drawable="@drawable/rocket_thrust2" android:duration="200" /&gt;
    &lt;item android:drawable="@drawable/rocket_thrust3" android:duration="200" /&gt;
&lt;/animation-list&gt;
</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>