• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.animation;
18 
19 import android.os.Handler;
20 import android.os.Looper;
21 import android.os.Message;
22 import android.util.AndroidRuntimeException;
23 import android.view.animation.AccelerateDecelerateInterpolator;
24 import android.view.animation.AnimationUtils;
25 import android.view.animation.LinearInterpolator;
26 
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 
30 /**
31  * This class provides a simple timing engine for running animations
32  * which calculate animated values and set them on target objects.
33  *
34  * <p>There is a single timing pulse that all animations use. It runs in a
35  * custom handler to ensure that property changes happen on the UI thread.</p>
36  *
37  * <p>By default, ValueAnimator uses non-linear time interpolation, via the
38  * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
39  * out of an animation. This behavior can be changed by calling
40  * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
41  */
42 public class ValueAnimator extends Animator {
43 
44     /**
45      * Internal constants
46      */
47 
48     /*
49      * The default amount of time in ms between animation frames
50      */
51     private static final long DEFAULT_FRAME_DELAY = 10;
52 
53     /**
54      * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent
55      * by the handler to itself to process the next animation frame
56      */
57     static final int ANIMATION_START = 0;
58     static final int ANIMATION_FRAME = 1;
59 
60     /**
61      * Values used with internal variable mPlayingState to indicate the current state of an
62      * animation.
63      */
64     static final int STOPPED    = 0; // Not yet playing
65     static final int RUNNING    = 1; // Playing normally
66     static final int SEEKED     = 2; // Seeked to some time value
67 
68     /**
69      * Internal variables
70      * NOTE: This object implements the clone() method, making a deep copy of any referenced
71      * objects. As other non-trivial fields are added to this class, make sure to add logic
72      * to clone() to make deep copies of them.
73      */
74 
75     // The first time that the animation's animateFrame() method is called. This time is used to
76     // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
77     // to animateFrame()
78     long mStartTime;
79 
80     /**
81      * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
82      * to a value.
83      */
84     long mSeekTime = -1;
85 
86     // TODO: We access the following ThreadLocal variables often, some of them on every update.
87     // If ThreadLocal access is significantly expensive, we may want to put all of these
88     // fields into a structure sot hat we just access ThreadLocal once to get the reference
89     // to that structure, then access the structure directly for each field.
90 
91     // The static sAnimationHandler processes the internal timing loop on which all animations
92     // are based
93     private static ThreadLocal<AnimationHandler> sAnimationHandler =
94             new ThreadLocal<AnimationHandler>();
95 
96     // The per-thread list of all active animations
97     private static final ThreadLocal<ArrayList<ValueAnimator>> sAnimations =
98             new ThreadLocal<ArrayList<ValueAnimator>>() {
99                 @Override
100                 protected ArrayList<ValueAnimator> initialValue() {
101                     return new ArrayList<ValueAnimator>();
102                 }
103             };
104 
105     // The per-thread set of animations to be started on the next animation frame
106     private static final ThreadLocal<ArrayList<ValueAnimator>> sPendingAnimations =
107             new ThreadLocal<ArrayList<ValueAnimator>>() {
108                 @Override
109                 protected ArrayList<ValueAnimator> initialValue() {
110                     return new ArrayList<ValueAnimator>();
111                 }
112             };
113 
114     /**
115      * Internal per-thread collections used to avoid set collisions as animations start and end
116      * while being processed.
117      */
118     private static final ThreadLocal<ArrayList<ValueAnimator>> sDelayedAnims =
119             new ThreadLocal<ArrayList<ValueAnimator>>() {
120                 @Override
121                 protected ArrayList<ValueAnimator> initialValue() {
122                     return new ArrayList<ValueAnimator>();
123                 }
124             };
125 
126     private static final ThreadLocal<ArrayList<ValueAnimator>> sEndingAnims =
127             new ThreadLocal<ArrayList<ValueAnimator>>() {
128                 @Override
129                 protected ArrayList<ValueAnimator> initialValue() {
130                     return new ArrayList<ValueAnimator>();
131                 }
132             };
133 
134     private static final ThreadLocal<ArrayList<ValueAnimator>> sReadyAnims =
135             new ThreadLocal<ArrayList<ValueAnimator>>() {
136                 @Override
137                 protected ArrayList<ValueAnimator> initialValue() {
138                     return new ArrayList<ValueAnimator>();
139                 }
140             };
141 
142     // The time interpolator to be used if none is set on the animation
143     private static final TimeInterpolator sDefaultInterpolator =
144             new AccelerateDecelerateInterpolator();
145 
146     // type evaluators for the primitive types handled by this implementation
147     private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
148     private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
149 
150     /**
151      * Used to indicate whether the animation is currently playing in reverse. This causes the
152      * elapsed fraction to be inverted to calculate the appropriate values.
153      */
154     private boolean mPlayingBackwards = false;
155 
156     /**
157      * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
158      * repeatCount (if repeatCount!=INFINITE), the animation ends
159      */
160     private int mCurrentIteration = 0;
161 
162     /**
163      * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
164      */
165     private float mCurrentFraction = 0f;
166 
167     /**
168      * Tracks whether a startDelay'd animation has begun playing through the startDelay.
169      */
170     private boolean mStartedDelay = false;
171 
172     /**
173      * Tracks the time at which the animation began playing through its startDelay. This is
174      * different from the mStartTime variable, which is used to track when the animation became
175      * active (which is when the startDelay expired and the animation was added to the active
176      * animations list).
177      */
178     private long mDelayStartTime;
179 
180     /**
181      * Flag that represents the current state of the animation. Used to figure out when to start
182      * an animation (if state == STOPPED). Also used to end an animation that
183      * has been cancel()'d or end()'d since the last animation frame. Possible values are
184      * STOPPED, RUNNING, SEEKED.
185      */
186     int mPlayingState = STOPPED;
187 
188     /**
189      * Additional playing state to indicate whether an animator has been start()'d. There is
190      * some lag between a call to start() and the first animation frame. We should still note
191      * that the animation has been started, even if it's first animation frame has not yet
192      * happened, and reflect that state in isRunning().
193      * Note that delayed animations are different: they are not started until their first
194      * animation frame, which occurs after their delay elapses.
195      */
196     private boolean mRunning = false;
197 
198     /**
199      * Additional playing state to indicate whether an animator has been start()'d, whether or
200      * not there is a nonzero startDelay.
201      */
202     private boolean mStarted = false;
203 
204     /**
205      * Flag that denotes whether the animation is set up and ready to go. Used to
206      * set up animation that has not yet been started.
207      */
208     boolean mInitialized = false;
209 
210     //
211     // Backing variables
212     //
213 
214     // How long the animation should last in ms
215     private long mDuration = 300;
216 
217     // The amount of time in ms to delay starting the animation after start() is called
218     private long mStartDelay = 0;
219 
220     // The number of milliseconds between animation frames
221     private static long sFrameDelay = DEFAULT_FRAME_DELAY;
222 
223     // The number of times the animation will repeat. The default is 0, which means the animation
224     // will play only once
225     private int mRepeatCount = 0;
226 
227     /**
228      * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
229      * animation will start from the beginning on every new cycle. REVERSE means the animation
230      * will reverse directions on each iteration.
231      */
232     private int mRepeatMode = RESTART;
233 
234     /**
235      * The time interpolator to be used. The elapsed fraction of the animation will be passed
236      * through this interpolator to calculate the interpolated fraction, which is then used to
237      * calculate the animated values.
238      */
239     private TimeInterpolator mInterpolator = sDefaultInterpolator;
240 
241     /**
242      * The set of listeners to be sent events through the life of an animation.
243      */
244     private ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
245 
246     /**
247      * The property/value sets being animated.
248      */
249     PropertyValuesHolder[] mValues;
250 
251     /**
252      * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
253      * by property name during calls to getAnimatedValue(String).
254      */
255     HashMap<String, PropertyValuesHolder> mValuesMap;
256 
257     /**
258      * Public constants
259      */
260 
261     /**
262      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
263      * or a positive value, the animation restarts from the beginning.
264      */
265     public static final int RESTART = 1;
266     /**
267      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
268      * or a positive value, the animation reverses direction on every iteration.
269      */
270     public static final int REVERSE = 2;
271     /**
272      * This value used used with the {@link #setRepeatCount(int)} property to repeat
273      * the animation indefinitely.
274      */
275     public static final int INFINITE = -1;
276 
277     /**
278      * Creates a new ValueAnimator object. This default constructor is primarily for
279      * use internally; the factory methods which take parameters are more generally
280      * useful.
281      */
ValueAnimator()282     public ValueAnimator() {
283     }
284 
285     /**
286      * Constructs and returns a ValueAnimator that animates between int values. A single
287      * value implies that that value is the one being animated to. However, this is not typically
288      * useful in a ValueAnimator object because there is no way for the object to determine the
289      * starting value for the animation (unlike ObjectAnimator, which can derive that value
290      * from the target object and property being animated). Therefore, there should typically
291      * be two or more values.
292      *
293      * @param values A set of values that the animation will animate between over time.
294      * @return A ValueAnimator object that is set up to animate between the given values.
295      */
ofInt(int... values)296     public static ValueAnimator ofInt(int... values) {
297         ValueAnimator anim = new ValueAnimator();
298         anim.setIntValues(values);
299         return anim;
300     }
301 
302     /**
303      * Constructs and returns a ValueAnimator that animates between float values. A single
304      * value implies that that value is the one being animated to. However, this is not typically
305      * useful in a ValueAnimator object because there is no way for the object to determine the
306      * starting value for the animation (unlike ObjectAnimator, which can derive that value
307      * from the target object and property being animated). Therefore, there should typically
308      * be two or more values.
309      *
310      * @param values A set of values that the animation will animate between over time.
311      * @return A ValueAnimator object that is set up to animate between the given values.
312      */
ofFloat(float... values)313     public static ValueAnimator ofFloat(float... values) {
314         ValueAnimator anim = new ValueAnimator();
315         anim.setFloatValues(values);
316         return anim;
317     }
318 
319     /**
320      * Constructs and returns a ValueAnimator that animates between the values
321      * specified in the PropertyValuesHolder objects.
322      *
323      * @param values A set of PropertyValuesHolder objects whose values will be animated
324      * between over time.
325      * @return A ValueAnimator object that is set up to animate between the given values.
326      */
ofPropertyValuesHolder(PropertyValuesHolder... values)327     public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
328         ValueAnimator anim = new ValueAnimator();
329         anim.setValues(values);
330         return anim;
331     }
332     /**
333      * Constructs and returns a ValueAnimator that animates between Object values. A single
334      * value implies that that value is the one being animated to. However, this is not typically
335      * useful in a ValueAnimator object because there is no way for the object to determine the
336      * starting value for the animation (unlike ObjectAnimator, which can derive that value
337      * from the target object and property being animated). Therefore, there should typically
338      * be two or more values.
339      *
340      * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
341      * factory method also takes a TypeEvaluator object that the ValueAnimator will use
342      * to perform that interpolation.
343      *
344      * @param evaluator A TypeEvaluator that will be called on each animation frame to
345      * provide the ncessry interpolation between the Object values to derive the animated
346      * value.
347      * @param values A set of values that the animation will animate between over time.
348      * @return A ValueAnimator object that is set up to animate between the given values.
349      */
ofObject(TypeEvaluator evaluator, Object... values)350     public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
351         ValueAnimator anim = new ValueAnimator();
352         anim.setObjectValues(values);
353         anim.setEvaluator(evaluator);
354         return anim;
355     }
356 
357     /**
358      * Sets int values that will be animated between. A single
359      * value implies that that value is the one being animated to. However, this is not typically
360      * useful in a ValueAnimator object because there is no way for the object to determine the
361      * starting value for the animation (unlike ObjectAnimator, which can derive that value
362      * from the target object and property being animated). Therefore, there should typically
363      * be two or more values.
364      *
365      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
366      * than one PropertyValuesHolder object, this method will set the values for the first
367      * of those objects.</p>
368      *
369      * @param values A set of values that the animation will animate between over time.
370      */
setIntValues(int... values)371     public void setIntValues(int... values) {
372         if (values == null || values.length == 0) {
373             return;
374         }
375         if (mValues == null || mValues.length == 0) {
376             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)});
377         } else {
378             PropertyValuesHolder valuesHolder = mValues[0];
379             valuesHolder.setIntValues(values);
380         }
381         // New property/values/target should cause re-initialization prior to starting
382         mInitialized = false;
383     }
384 
385     /**
386      * Sets float values that will be animated between. A single
387      * value implies that that value is the one being animated to. However, this is not typically
388      * useful in a ValueAnimator object because there is no way for the object to determine the
389      * starting value for the animation (unlike ObjectAnimator, which can derive that value
390      * from the target object and property being animated). Therefore, there should typically
391      * be two or more values.
392      *
393      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
394      * than one PropertyValuesHolder object, this method will set the values for the first
395      * of those objects.</p>
396      *
397      * @param values A set of values that the animation will animate between over time.
398      */
setFloatValues(float... values)399     public void setFloatValues(float... values) {
400         if (values == null || values.length == 0) {
401             return;
402         }
403         if (mValues == null || mValues.length == 0) {
404             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)});
405         } else {
406             PropertyValuesHolder valuesHolder = mValues[0];
407             valuesHolder.setFloatValues(values);
408         }
409         // New property/values/target should cause re-initialization prior to starting
410         mInitialized = false;
411     }
412 
413     /**
414      * Sets the values to animate between for this animation. A single
415      * value implies that that value is the one being animated to. However, this is not typically
416      * useful in a ValueAnimator object because there is no way for the object to determine the
417      * starting value for the animation (unlike ObjectAnimator, which can derive that value
418      * from the target object and property being animated). Therefore, there should typically
419      * be two or more values.
420      *
421      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
422      * than one PropertyValuesHolder object, this method will set the values for the first
423      * of those objects.</p>
424      *
425      * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
426      * between these value objects. ValueAnimator only knows how to interpolate between the
427      * primitive types specified in the other setValues() methods.</p>
428      *
429      * @param values The set of values to animate between.
430      */
setObjectValues(Object... values)431     public void setObjectValues(Object... values) {
432         if (values == null || values.length == 0) {
433             return;
434         }
435         if (mValues == null || mValues.length == 0) {
436             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("",
437                     (TypeEvaluator)null, values)});
438         } else {
439             PropertyValuesHolder valuesHolder = mValues[0];
440             valuesHolder.setObjectValues(values);
441         }
442         // New property/values/target should cause re-initialization prior to starting
443         mInitialized = false;
444     }
445 
446     /**
447      * Sets the values, per property, being animated between. This function is called internally
448      * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can
449      * be constructed without values and this method can be called to set the values manually
450      * instead.
451      *
452      * @param values The set of values, per property, being animated between.
453      */
setValues(PropertyValuesHolder... values)454     public void setValues(PropertyValuesHolder... values) {
455         int numValues = values.length;
456         mValues = values;
457         mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
458         for (int i = 0; i < numValues; ++i) {
459             PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
460             mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
461         }
462         // New property/values/target should cause re-initialization prior to starting
463         mInitialized = false;
464     }
465 
466     /**
467      * Returns the values that this ValueAnimator animates between. These values are stored in
468      * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
469      * of value objects instead.
470      *
471      * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
472      * values, per property, that define the animation.
473      */
getValues()474     public PropertyValuesHolder[] getValues() {
475         return mValues;
476     }
477 
478     /**
479      * This function is called immediately before processing the first animation
480      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
481      * function is called after that delay ends.
482      * It takes care of the final initialization steps for the
483      * animation.
484      *
485      *  <p>Overrides of this method should call the superclass method to ensure
486      *  that internal mechanisms for the animation are set up correctly.</p>
487      */
initAnimation()488     void initAnimation() {
489         if (!mInitialized) {
490             int numValues = mValues.length;
491             for (int i = 0; i < numValues; ++i) {
492                 mValues[i].init();
493             }
494             mInitialized = true;
495         }
496     }
497 
498 
499     /**
500      * Sets the length of the animation. The default duration is 300 milliseconds.
501      *
502      * @param duration The length of the animation, in milliseconds. This value cannot
503      * be negative.
504      * @return ValueAnimator The object called with setDuration(). This return
505      * value makes it easier to compose statements together that construct and then set the
506      * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
507      */
setDuration(long duration)508     public ValueAnimator setDuration(long duration) {
509         if (duration < 0) {
510             throw new IllegalArgumentException("Animators cannot have negative duration: " +
511                     duration);
512         }
513         mDuration = duration;
514         return this;
515     }
516 
517     /**
518      * Gets the length of the animation. The default duration is 300 milliseconds.
519      *
520      * @return The length of the animation, in milliseconds.
521      */
getDuration()522     public long getDuration() {
523         return mDuration;
524     }
525 
526     /**
527      * Sets the position of the animation to the specified point in time. This time should
528      * be between 0 and the total duration of the animation, including any repetition. If
529      * the animation has not yet been started, then it will not advance forward after it is
530      * set to this time; it will simply set the time to this value and perform any appropriate
531      * actions based on that time. If the animation is already running, then setCurrentPlayTime()
532      * will set the current playing time to this value and continue playing from that point.
533      *
534      * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
535      */
setCurrentPlayTime(long playTime)536     public void setCurrentPlayTime(long playTime) {
537         initAnimation();
538         long currentTime = AnimationUtils.currentAnimationTimeMillis();
539         if (mPlayingState != RUNNING) {
540             mSeekTime = playTime;
541             mPlayingState = SEEKED;
542         }
543         mStartTime = currentTime - playTime;
544         animationFrame(currentTime);
545     }
546 
547     /**
548      * Gets the current position of the animation in time, which is equal to the current
549      * time minus the time that the animation started. An animation that is not yet started will
550      * return a value of zero.
551      *
552      * @return The current position in time of the animation.
553      */
getCurrentPlayTime()554     public long getCurrentPlayTime() {
555         if (!mInitialized || mPlayingState == STOPPED) {
556             return 0;
557         }
558         return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
559     }
560 
561     /**
562      * This custom, static handler handles the timing pulse that is shared by
563      * all active animations. This approach ensures that the setting of animation
564      * values will happen on the UI thread and that all animations will share
565      * the same times for calculating their values, which makes synchronizing
566      * animations possible.
567      *
568      */
569     private static class AnimationHandler extends Handler {
570         /**
571          * There are only two messages that we care about: ANIMATION_START and
572          * ANIMATION_FRAME. The START message is sent when an animation's start()
573          * method is called. It cannot start synchronously when start() is called
574          * because the call may be on the wrong thread, and it would also not be
575          * synchronized with other animations because it would not start on a common
576          * timing pulse. So each animation sends a START message to the handler, which
577          * causes the handler to place the animation on the active animations queue and
578          * start processing frames for that animation.
579          * The FRAME message is the one that is sent over and over while there are any
580          * active animations to process.
581          */
582         @Override
handleMessage(Message msg)583         public void handleMessage(Message msg) {
584             boolean callAgain = true;
585             ArrayList<ValueAnimator> animations = sAnimations.get();
586             ArrayList<ValueAnimator> delayedAnims = sDelayedAnims.get();
587             switch (msg.what) {
588                 // TODO: should we avoid sending frame message when starting if we
589                 // were already running?
590                 case ANIMATION_START:
591                     ArrayList<ValueAnimator> pendingAnimations = sPendingAnimations.get();
592                     if (animations.size() > 0 || delayedAnims.size() > 0) {
593                         callAgain = false;
594                     }
595                     // pendingAnims holds any animations that have requested to be started
596                     // We're going to clear sPendingAnimations, but starting animation may
597                     // cause more to be added to the pending list (for example, if one animation
598                     // starting triggers another starting). So we loop until sPendingAnimations
599                     // is empty.
600                     while (pendingAnimations.size() > 0) {
601                         ArrayList<ValueAnimator> pendingCopy =
602                                 (ArrayList<ValueAnimator>) pendingAnimations.clone();
603                         pendingAnimations.clear();
604                         int count = pendingCopy.size();
605                         for (int i = 0; i < count; ++i) {
606                             ValueAnimator anim = pendingCopy.get(i);
607                             // If the animation has a startDelay, place it on the delayed list
608                             if (anim.mStartDelay == 0) {
609                                 anim.startAnimation();
610                             } else {
611                                 delayedAnims.add(anim);
612                             }
613                         }
614                     }
615                     // fall through to process first frame of new animations
616                 case ANIMATION_FRAME:
617                     // currentTime holds the common time for all animations processed
618                     // during this frame
619                     long currentTime = AnimationUtils.currentAnimationTimeMillis();
620                     ArrayList<ValueAnimator> readyAnims = sReadyAnims.get();
621                     ArrayList<ValueAnimator> endingAnims = sEndingAnims.get();
622 
623                     // First, process animations currently sitting on the delayed queue, adding
624                     // them to the active animations if they are ready
625                     int numDelayedAnims = delayedAnims.size();
626                     for (int i = 0; i < numDelayedAnims; ++i) {
627                         ValueAnimator anim = delayedAnims.get(i);
628                         if (anim.delayedAnimationFrame(currentTime)) {
629                             readyAnims.add(anim);
630                         }
631                     }
632                     int numReadyAnims = readyAnims.size();
633                     if (numReadyAnims > 0) {
634                         for (int i = 0; i < numReadyAnims; ++i) {
635                             ValueAnimator anim = readyAnims.get(i);
636                             anim.startAnimation();
637                             anim.mRunning = true;
638                             delayedAnims.remove(anim);
639                         }
640                         readyAnims.clear();
641                     }
642 
643                     // Now process all active animations. The return value from animationFrame()
644                     // tells the handler whether it should now be ended
645                     int numAnims = animations.size();
646                     int i = 0;
647                     while (i < numAnims) {
648                         ValueAnimator anim = animations.get(i);
649                         if (anim.animationFrame(currentTime)) {
650                             endingAnims.add(anim);
651                         }
652                         if (animations.size() == numAnims) {
653                             ++i;
654                         } else {
655                             // An animation might be canceled or ended by client code
656                             // during the animation frame. Check to see if this happened by
657                             // seeing whether the current index is the same as it was before
658                             // calling animationFrame(). Another approach would be to copy
659                             // animations to a temporary list and process that list instead,
660                             // but that entails garbage and processing overhead that would
661                             // be nice to avoid.
662                             --numAnims;
663                             endingAnims.remove(anim);
664                         }
665                     }
666                     if (endingAnims.size() > 0) {
667                         for (i = 0; i < endingAnims.size(); ++i) {
668                             endingAnims.get(i).endAnimation();
669                         }
670                         endingAnims.clear();
671                     }
672 
673                     // If there are still active or delayed animations, call the handler again
674                     // after the frameDelay
675                     if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) {
676                         sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
677                             (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
678                     }
679                     break;
680             }
681         }
682     }
683 
684     /**
685      * The amount of time, in milliseconds, to delay starting the animation after
686      * {@link #start()} is called.
687      *
688      * @return the number of milliseconds to delay running the animation
689      */
getStartDelay()690     public long getStartDelay() {
691         return mStartDelay;
692     }
693 
694     /**
695      * The amount of time, in milliseconds, to delay starting the animation after
696      * {@link #start()} is called.
697 
698      * @param startDelay The amount of the delay, in milliseconds
699      */
setStartDelay(long startDelay)700     public void setStartDelay(long startDelay) {
701         this.mStartDelay = startDelay;
702     }
703 
704     /**
705      * The amount of time, in milliseconds, between each frame of the animation. This is a
706      * requested time that the animation will attempt to honor, but the actual delay between
707      * frames may be different, depending on system load and capabilities. This is a static
708      * function because the same delay will be applied to all animations, since they are all
709      * run off of a single timing loop.
710      *
711      * @return the requested time between frames, in milliseconds
712      */
getFrameDelay()713     public static long getFrameDelay() {
714         return sFrameDelay;
715     }
716 
717     /**
718      * The amount of time, in milliseconds, between each frame of the animation. This is a
719      * requested time that the animation will attempt to honor, but the actual delay between
720      * frames may be different, depending on system load and capabilities. This is a static
721      * function because the same delay will be applied to all animations, since they are all
722      * run off of a single timing loop.
723      *
724      * @param frameDelay the requested time between frames, in milliseconds
725      */
setFrameDelay(long frameDelay)726     public static void setFrameDelay(long frameDelay) {
727         sFrameDelay = frameDelay;
728     }
729 
730     /**
731      * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
732      * property being animated. This value is only sensible while the animation is running. The main
733      * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
734      * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
735      * is called during each animation frame, immediately after the value is calculated.
736      *
737      * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
738      * the single property being animated. If there are several properties being animated
739      * (specified by several PropertyValuesHolder objects in the constructor), this function
740      * returns the animated value for the first of those objects.
741      */
getAnimatedValue()742     public Object getAnimatedValue() {
743         if (mValues != null && mValues.length > 0) {
744             return mValues[0].getAnimatedValue();
745         }
746         // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
747         return null;
748     }
749 
750     /**
751      * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
752      * The main purpose for this read-only property is to retrieve the value from the
753      * <code>ValueAnimator</code> during a call to
754      * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
755      * is called during each animation frame, immediately after the value is calculated.
756      *
757      * @return animatedValue The value most recently calculated for the named property
758      * by this <code>ValueAnimator</code>.
759      */
getAnimatedValue(String propertyName)760     public Object getAnimatedValue(String propertyName) {
761         PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
762         if (valuesHolder != null) {
763             return valuesHolder.getAnimatedValue();
764         } else {
765             // At least avoid crashing if called with bogus propertyName
766             return null;
767         }
768     }
769 
770     /**
771      * Sets how many times the animation should be repeated. If the repeat
772      * count is 0, the animation is never repeated. If the repeat count is
773      * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
774      * into account. The repeat count is 0 by default.
775      *
776      * @param value the number of times the animation should be repeated
777      */
setRepeatCount(int value)778     public void setRepeatCount(int value) {
779         mRepeatCount = value;
780     }
781     /**
782      * Defines how many times the animation should repeat. The default value
783      * is 0.
784      *
785      * @return the number of times the animation should repeat, or {@link #INFINITE}
786      */
getRepeatCount()787     public int getRepeatCount() {
788         return mRepeatCount;
789     }
790 
791     /**
792      * Defines what this animation should do when it reaches the end. This
793      * setting is applied only when the repeat count is either greater than
794      * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
795      *
796      * @param value {@link #RESTART} or {@link #REVERSE}
797      */
setRepeatMode(int value)798     public void setRepeatMode(int value) {
799         mRepeatMode = value;
800     }
801 
802     /**
803      * Defines what this animation should do when it reaches the end.
804      *
805      * @return either one of {@link #REVERSE} or {@link #RESTART}
806      */
getRepeatMode()807     public int getRepeatMode() {
808         return mRepeatMode;
809     }
810 
811     /**
812      * Adds a listener to the set of listeners that are sent update events through the life of
813      * an animation. This method is called on all listeners for every frame of the animation,
814      * after the values for the animation have been calculated.
815      *
816      * @param listener the listener to be added to the current set of listeners for this animation.
817      */
addUpdateListener(AnimatorUpdateListener listener)818     public void addUpdateListener(AnimatorUpdateListener listener) {
819         if (mUpdateListeners == null) {
820             mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
821         }
822         mUpdateListeners.add(listener);
823     }
824 
825     /**
826      * Removes all listeners from the set listening to frame updates for this animation.
827      */
removeAllUpdateListeners()828     public void removeAllUpdateListeners() {
829         if (mUpdateListeners == null) {
830             return;
831         }
832         mUpdateListeners.clear();
833         mUpdateListeners = null;
834     }
835 
836     /**
837      * Removes a listener from the set listening to frame updates for this animation.
838      *
839      * @param listener the listener to be removed from the current set of update listeners
840      * for this animation.
841      */
removeUpdateListener(AnimatorUpdateListener listener)842     public void removeUpdateListener(AnimatorUpdateListener listener) {
843         if (mUpdateListeners == null) {
844             return;
845         }
846         mUpdateListeners.remove(listener);
847         if (mUpdateListeners.size() == 0) {
848             mUpdateListeners = null;
849         }
850     }
851 
852 
853     /**
854      * The time interpolator used in calculating the elapsed fraction of this animation. The
855      * interpolator determines whether the animation runs with linear or non-linear motion,
856      * such as acceleration and deceleration. The default value is
857      * {@link android.view.animation.AccelerateDecelerateInterpolator}
858      *
859      * @param value the interpolator to be used by this animation. A value of <code>null</code>
860      * will result in linear interpolation.
861      */
862     @Override
setInterpolator(TimeInterpolator value)863     public void setInterpolator(TimeInterpolator value) {
864         if (value != null) {
865             mInterpolator = value;
866         } else {
867             mInterpolator = new LinearInterpolator();
868         }
869     }
870 
871     /**
872      * Returns the timing interpolator that this ValueAnimator uses.
873      *
874      * @return The timing interpolator for this ValueAnimator.
875      */
getInterpolator()876     public TimeInterpolator getInterpolator() {
877         return mInterpolator;
878     }
879 
880     /**
881      * The type evaluator to be used when calculating the animated values of this animation.
882      * The system will automatically assign a float or int evaluator based on the type
883      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
884      * are not one of these primitive types, or if different evaluation is desired (such as is
885      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
886      * For example, when running an animation on color values, the {@link ArgbEvaluator}
887      * should be used to get correct RGB color interpolation.
888      *
889      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
890      * will be used for that set. If there are several sets of values being animated, which is
891      * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator
892      * is assigned just to the first PropertyValuesHolder object.</p>
893      *
894      * @param value the evaluator to be used this animation
895      */
setEvaluator(TypeEvaluator value)896     public void setEvaluator(TypeEvaluator value) {
897         if (value != null && mValues != null && mValues.length > 0) {
898             mValues[0].setEvaluator(value);
899         }
900     }
901 
902     /**
903      * Start the animation playing. This version of start() takes a boolean flag that indicates
904      * whether the animation should play in reverse. The flag is usually false, but may be set
905      * to true if called from the reverse() method.
906      *
907      * <p>The animation started by calling this method will be run on the thread that called
908      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
909      * this is not the case). Also, if the animation will animate
910      * properties of objects in the view hierarchy, then the calling thread should be the UI
911      * thread for that view hierarchy.</p>
912      *
913      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
914      */
start(boolean playBackwards)915     private void start(boolean playBackwards) {
916         if (Looper.myLooper() == null) {
917             throw new AndroidRuntimeException("Animators may only be run on Looper threads");
918         }
919         mPlayingBackwards = playBackwards;
920         mCurrentIteration = 0;
921         mPlayingState = STOPPED;
922         mStarted = true;
923         mStartedDelay = false;
924         sPendingAnimations.get().add(this);
925         if (mStartDelay == 0) {
926             // This sets the initial value of the animation, prior to actually starting it running
927             setCurrentPlayTime(getCurrentPlayTime());
928             mPlayingState = STOPPED;
929             mRunning = true;
930 
931             if (mListeners != null) {
932                 ArrayList<AnimatorListener> tmpListeners =
933                         (ArrayList<AnimatorListener>) mListeners.clone();
934                 int numListeners = tmpListeners.size();
935                 for (int i = 0; i < numListeners; ++i) {
936                     tmpListeners.get(i).onAnimationStart(this);
937                 }
938             }
939         }
940         AnimationHandler animationHandler = sAnimationHandler.get();
941         if (animationHandler == null) {
942             animationHandler = new AnimationHandler();
943             sAnimationHandler.set(animationHandler);
944         }
945         animationHandler.sendEmptyMessage(ANIMATION_START);
946     }
947 
948     @Override
start()949     public void start() {
950         start(false);
951     }
952 
953     @Override
cancel()954     public void cancel() {
955         // Only cancel if the animation is actually running or has been started and is about
956         // to run
957         if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
958                 sDelayedAnims.get().contains(this)) {
959             // Only notify listeners if the animator has actually started
960             if (mRunning && mListeners != null) {
961                 ArrayList<AnimatorListener> tmpListeners =
962                         (ArrayList<AnimatorListener>) mListeners.clone();
963                 for (AnimatorListener listener : tmpListeners) {
964                     listener.onAnimationCancel(this);
965                 }
966             }
967             endAnimation();
968         }
969     }
970 
971     @Override
end()972     public void end() {
973         if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
974             // Special case if the animation has not yet started; get it ready for ending
975             mStartedDelay = false;
976             startAnimation();
977         } else if (!mInitialized) {
978             initAnimation();
979         }
980         // The final value set on the target varies, depending on whether the animation
981         // was supposed to repeat an odd number of times
982         if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
983             animateValue(0f);
984         } else {
985             animateValue(1f);
986         }
987         endAnimation();
988     }
989 
990     @Override
isRunning()991     public boolean isRunning() {
992         return (mPlayingState == RUNNING || mRunning);
993     }
994 
995     @Override
isStarted()996     public boolean isStarted() {
997         return mStarted;
998     }
999 
1000     /**
1001      * Plays the ValueAnimator in reverse. If the animation is already running,
1002      * it will stop itself and play backwards from the point reached when reverse was called.
1003      * If the animation is not currently running, then it will start from the end and
1004      * play backwards. This behavior is only set for the current animation; future playing
1005      * of the animation will use the default behavior of playing forward.
1006      */
reverse()1007     public void reverse() {
1008         mPlayingBackwards = !mPlayingBackwards;
1009         if (mPlayingState == RUNNING) {
1010             long currentTime = AnimationUtils.currentAnimationTimeMillis();
1011             long currentPlayTime = currentTime - mStartTime;
1012             long timeLeft = mDuration - currentPlayTime;
1013             mStartTime = currentTime - timeLeft;
1014         } else {
1015             start(true);
1016         }
1017     }
1018 
1019     /**
1020      * Called internally to end an animation by removing it from the animations list. Must be
1021      * called on the UI thread.
1022      */
endAnimation()1023     private void endAnimation() {
1024         sAnimations.get().remove(this);
1025         sPendingAnimations.get().remove(this);
1026         sDelayedAnims.get().remove(this);
1027         mPlayingState = STOPPED;
1028         if (mRunning && mListeners != null) {
1029             ArrayList<AnimatorListener> tmpListeners =
1030                     (ArrayList<AnimatorListener>) mListeners.clone();
1031             int numListeners = tmpListeners.size();
1032             for (int i = 0; i < numListeners; ++i) {
1033                 tmpListeners.get(i).onAnimationEnd(this);
1034             }
1035         }
1036         mRunning = false;
1037         mStarted = false;
1038     }
1039 
1040     /**
1041      * Called internally to start an animation by adding it to the active animations list. Must be
1042      * called on the UI thread.
1043      */
startAnimation()1044     private void startAnimation() {
1045         initAnimation();
1046         sAnimations.get().add(this);
1047         if (mStartDelay > 0 && mListeners != null) {
1048             // Listeners were already notified in start() if startDelay is 0; this is
1049             // just for delayed animations
1050             ArrayList<AnimatorListener> tmpListeners =
1051                     (ArrayList<AnimatorListener>) mListeners.clone();
1052             int numListeners = tmpListeners.size();
1053             for (int i = 0; i < numListeners; ++i) {
1054                 tmpListeners.get(i).onAnimationStart(this);
1055             }
1056         }
1057     }
1058 
1059     /**
1060      * Internal function called to process an animation frame on an animation that is currently
1061      * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
1062      * should be woken up and put on the active animations queue.
1063      *
1064      * @param currentTime The current animation time, used to calculate whether the animation
1065      * has exceeded its <code>startDelay</code> and should be started.
1066      * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
1067      * should be added to the set of active animations.
1068      */
delayedAnimationFrame(long currentTime)1069     private boolean delayedAnimationFrame(long currentTime) {
1070         if (!mStartedDelay) {
1071             mStartedDelay = true;
1072             mDelayStartTime = currentTime;
1073         } else {
1074             long deltaTime = currentTime - mDelayStartTime;
1075             if (deltaTime > mStartDelay) {
1076                 // startDelay ended - start the anim and record the
1077                 // mStartTime appropriately
1078                 mStartTime = currentTime - (deltaTime - mStartDelay);
1079                 mPlayingState = RUNNING;
1080                 return true;
1081             }
1082         }
1083         return false;
1084     }
1085 
1086     /**
1087      * This internal function processes a single animation frame for a given animation. The
1088      * currentTime parameter is the timing pulse sent by the handler, used to calculate the
1089      * elapsed duration, and therefore
1090      * the elapsed fraction, of the animation. The return value indicates whether the animation
1091      * should be ended (which happens when the elapsed time of the animation exceeds the
1092      * animation's duration, including the repeatCount).
1093      *
1094      * @param currentTime The current time, as tracked by the static timing handler
1095      * @return true if the animation's duration, including any repetitions due to
1096      * <code>repeatCount</code> has been exceeded and the animation should be ended.
1097      */
animationFrame(long currentTime)1098     boolean animationFrame(long currentTime) {
1099         boolean done = false;
1100 
1101         if (mPlayingState == STOPPED) {
1102             mPlayingState = RUNNING;
1103             if (mSeekTime < 0) {
1104                 mStartTime = currentTime;
1105             } else {
1106                 mStartTime = currentTime - mSeekTime;
1107                 // Now that we're playing, reset the seek time
1108                 mSeekTime = -1;
1109             }
1110         }
1111         switch (mPlayingState) {
1112         case RUNNING:
1113         case SEEKED:
1114             float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
1115             if (fraction >= 1f) {
1116                 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
1117                     // Time to repeat
1118                     if (mListeners != null) {
1119                         int numListeners = mListeners.size();
1120                         for (int i = 0; i < numListeners; ++i) {
1121                             mListeners.get(i).onAnimationRepeat(this);
1122                         }
1123                     }
1124                     if (mRepeatMode == REVERSE) {
1125                         mPlayingBackwards = mPlayingBackwards ? false : true;
1126                     }
1127                     mCurrentIteration += (int)fraction;
1128                     fraction = fraction % 1f;
1129                     mStartTime += mDuration;
1130                 } else {
1131                     done = true;
1132                     fraction = Math.min(fraction, 1.0f);
1133                 }
1134             }
1135             if (mPlayingBackwards) {
1136                 fraction = 1f - fraction;
1137             }
1138             animateValue(fraction);
1139             break;
1140         }
1141 
1142         return done;
1143     }
1144 
1145     /**
1146      * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
1147      * the most recent frame update on the animation.
1148      *
1149      * @return Elapsed/interpolated fraction of the animation.
1150      */
getAnimatedFraction()1151     public float getAnimatedFraction() {
1152         return mCurrentFraction;
1153     }
1154 
1155     /**
1156      * This method is called with the elapsed fraction of the animation during every
1157      * animation frame. This function turns the elapsed fraction into an interpolated fraction
1158      * and then into an animated value (from the evaluator. The function is called mostly during
1159      * animation updates, but it is also called when the <code>end()</code>
1160      * function is called, to set the final value on the property.
1161      *
1162      * <p>Overrides of this method must call the superclass to perform the calculation
1163      * of the animated value.</p>
1164      *
1165      * @param fraction The elapsed fraction of the animation.
1166      */
animateValue(float fraction)1167     void animateValue(float fraction) {
1168         fraction = mInterpolator.getInterpolation(fraction);
1169         mCurrentFraction = fraction;
1170         int numValues = mValues.length;
1171         for (int i = 0; i < numValues; ++i) {
1172             mValues[i].calculateValue(fraction);
1173         }
1174         if (mUpdateListeners != null) {
1175             int numListeners = mUpdateListeners.size();
1176             for (int i = 0; i < numListeners; ++i) {
1177                 mUpdateListeners.get(i).onAnimationUpdate(this);
1178             }
1179         }
1180     }
1181 
1182     @Override
clone()1183     public ValueAnimator clone() {
1184         final ValueAnimator anim = (ValueAnimator) super.clone();
1185         if (mUpdateListeners != null) {
1186             ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
1187             anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
1188             int numListeners = oldListeners.size();
1189             for (int i = 0; i < numListeners; ++i) {
1190                 anim.mUpdateListeners.add(oldListeners.get(i));
1191             }
1192         }
1193         anim.mSeekTime = -1;
1194         anim.mPlayingBackwards = false;
1195         anim.mCurrentIteration = 0;
1196         anim.mInitialized = false;
1197         anim.mPlayingState = STOPPED;
1198         anim.mStartedDelay = false;
1199         PropertyValuesHolder[] oldValues = mValues;
1200         if (oldValues != null) {
1201             int numValues = oldValues.length;
1202             anim.mValues = new PropertyValuesHolder[numValues];
1203             anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
1204             for (int i = 0; i < numValues; ++i) {
1205                 PropertyValuesHolder newValuesHolder = oldValues[i].clone();
1206                 anim.mValues[i] = newValuesHolder;
1207                 anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
1208             }
1209         }
1210         return anim;
1211     }
1212 
1213     /**
1214      * Implementors of this interface can add themselves as update listeners
1215      * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
1216      * frame, after the current frame's values have been calculated for that
1217      * <code>ValueAnimator</code>.
1218      */
1219     public static interface AnimatorUpdateListener {
1220         /**
1221          * <p>Notifies the occurrence of another frame of the animation.</p>
1222          *
1223          * @param animation The animation which was repeated.
1224          */
onAnimationUpdate(ValueAnimator animation)1225         void onAnimationUpdate(ValueAnimator animation);
1226 
1227     }
1228 
1229     /**
1230      * Return the number of animations currently running.
1231      *
1232      * Used by StrictMode internally to annotate violations.  Only
1233      * called on the main thread.
1234      *
1235      * @hide
1236      */
getCurrentAnimationsCount()1237     public static int getCurrentAnimationsCount() {
1238         return sAnimations.get().size();
1239     }
1240 
1241     /**
1242      * Clear all animations on this thread, without canceling or ending them.
1243      * This should be used with caution.
1244      *
1245      * @hide
1246      */
clearAllAnimations()1247     public static void clearAllAnimations() {
1248         sAnimations.get().clear();
1249         sPendingAnimations.get().clear();
1250         sDelayedAnims.get().clear();
1251     }
1252 
1253     @Override
toString()1254     public String toString() {
1255         String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
1256         if (mValues != null) {
1257             for (int i = 0; i < mValues.length; ++i) {
1258                 returnVal += "\n    " + mValues[i].toString();
1259             }
1260         }
1261         return returnVal;
1262     }
1263 }
1264