• 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.content.res.ConfigurationBoundResourceCache;
20 import android.os.Looper;
21 import android.os.Trace;
22 import android.util.AndroidRuntimeException;
23 import android.view.Choreographer;
24 import android.view.animation.AccelerateDecelerateInterpolator;
25 import android.view.animation.AnimationUtils;
26 import android.view.animation.LinearInterpolator;
27 
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 
31 /**
32  * This class provides a simple timing engine for running animations
33  * which calculate animated values and set them on target objects.
34  *
35  * <p>There is a single timing pulse that all animations use. It runs in a
36  * custom handler to ensure that property changes happen on the UI thread.</p>
37  *
38  * <p>By default, ValueAnimator uses non-linear time interpolation, via the
39  * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
40  * out of an animation. This behavior can be changed by calling
41  * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
42  *
43  * <div class="special reference">
44  * <h3>Developer Guides</h3>
45  * <p>For more information about animating with {@code ValueAnimator}, read the
46  * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property
47  * Animation</a> developer guide.</p>
48  * </div>
49  */
50 @SuppressWarnings("unchecked")
51 public class ValueAnimator extends Animator {
52 
53     /**
54      * Internal constants
55      */
56     private static float sDurationScale = 1.0f;
57 
58     /**
59      * Values used with internal variable mPlayingState to indicate the current state of an
60      * animation.
61      */
62     static final int STOPPED    = 0; // Not yet playing
63     static final int RUNNING    = 1; // Playing normally
64     static final int SEEKED     = 2; // Seeked to some time value
65 
66     /**
67      * Internal variables
68      * NOTE: This object implements the clone() method, making a deep copy of any referenced
69      * objects. As other non-trivial fields are added to this class, make sure to add logic
70      * to clone() to make deep copies of them.
71      */
72 
73     // The first time that the animation's animateFrame() method is called. This time is used to
74     // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
75     // to animateFrame()
76     long mStartTime;
77 
78     /**
79      * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
80      * to a value.
81      */
82     float mSeekFraction = -1;
83 
84     /**
85      * Set on the next frame after pause() is called, used to calculate a new startTime
86      * or delayStartTime which allows the animator to continue from the point at which
87      * it was paused. If negative, has not yet been set.
88      */
89     private long mPauseTime;
90 
91     /**
92      * Set when an animator is resumed. This triggers logic in the next frame which
93      * actually resumes the animator.
94      */
95     private boolean mResumed = false;
96 
97 
98     // The static sAnimationHandler processes the internal timing loop on which all animations
99     // are based
100     /**
101      * @hide
102      */
103     protected static ThreadLocal<AnimationHandler> sAnimationHandler =
104             new ThreadLocal<AnimationHandler>();
105 
106     // The time interpolator to be used if none is set on the animation
107     private static final TimeInterpolator sDefaultInterpolator =
108             new AccelerateDecelerateInterpolator();
109 
110     /**
111      * Used to indicate whether the animation is currently playing in reverse. This causes the
112      * elapsed fraction to be inverted to calculate the appropriate values.
113      */
114     private boolean mPlayingBackwards = false;
115 
116     /**
117      * Flag to indicate whether this animator is playing in reverse mode, specifically
118      * by being started or interrupted by a call to reverse(). This flag is different than
119      * mPlayingBackwards, which indicates merely whether the current iteration of the
120      * animator is playing in reverse. It is used in corner cases to determine proper end
121      * behavior.
122      */
123     private boolean mReversing;
124 
125     /**
126      * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
127      * repeatCount (if repeatCount!=INFINITE), the animation ends
128      */
129     private int mCurrentIteration = 0;
130 
131     /**
132      * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
133      */
134     private float mCurrentFraction = 0f;
135 
136     /**
137      * Tracks whether a startDelay'd animation has begun playing through the startDelay.
138      */
139     private boolean mStartedDelay = false;
140 
141     /**
142      * Tracks the time at which the animation began playing through its startDelay. This is
143      * different from the mStartTime variable, which is used to track when the animation became
144      * active (which is when the startDelay expired and the animation was added to the active
145      * animations list).
146      */
147     private long mDelayStartTime;
148 
149     /**
150      * Flag that represents the current state of the animation. Used to figure out when to start
151      * an animation (if state == STOPPED). Also used to end an animation that
152      * has been cancel()'d or end()'d since the last animation frame. Possible values are
153      * STOPPED, RUNNING, SEEKED.
154      */
155     int mPlayingState = STOPPED;
156 
157     /**
158      * Additional playing state to indicate whether an animator has been start()'d. There is
159      * some lag between a call to start() and the first animation frame. We should still note
160      * that the animation has been started, even if it's first animation frame has not yet
161      * happened, and reflect that state in isRunning().
162      * Note that delayed animations are different: they are not started until their first
163      * animation frame, which occurs after their delay elapses.
164      */
165     private boolean mRunning = false;
166 
167     /**
168      * Additional playing state to indicate whether an animator has been start()'d, whether or
169      * not there is a nonzero startDelay.
170      */
171     private boolean mStarted = false;
172 
173     /**
174      * Tracks whether we've notified listeners of the onAnimationStart() event. This can be
175      * complex to keep track of since we notify listeners at different times depending on
176      * startDelay and whether start() was called before end().
177      */
178     private boolean mStartListenersCalled = false;
179 
180     /**
181      * Flag that denotes whether the animation is set up and ready to go. Used to
182      * set up animation that has not yet been started.
183      */
184     boolean mInitialized = false;
185 
186     //
187     // Backing variables
188     //
189 
190     // How long the animation should last in ms
191     private long mDuration = (long)(300 * sDurationScale);
192     private long mUnscaledDuration = 300;
193 
194     // The amount of time in ms to delay starting the animation after start() is called
195     private long mStartDelay = 0;
196     private long mUnscaledStartDelay = 0;
197 
198     // The number of times the animation will repeat. The default is 0, which means the animation
199     // will play only once
200     private int mRepeatCount = 0;
201 
202     /**
203      * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
204      * animation will start from the beginning on every new cycle. REVERSE means the animation
205      * will reverse directions on each iteration.
206      */
207     private int mRepeatMode = RESTART;
208 
209     /**
210      * The time interpolator to be used. The elapsed fraction of the animation will be passed
211      * through this interpolator to calculate the interpolated fraction, which is then used to
212      * calculate the animated values.
213      */
214     private TimeInterpolator mInterpolator = sDefaultInterpolator;
215 
216     /**
217      * The set of listeners to be sent events through the life of an animation.
218      */
219     ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
220 
221     /**
222      * The property/value sets being animated.
223      */
224     PropertyValuesHolder[] mValues;
225 
226     /**
227      * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
228      * by property name during calls to getAnimatedValue(String).
229      */
230     HashMap<String, PropertyValuesHolder> mValuesMap;
231 
232     /**
233      * Public constants
234      */
235 
236     /**
237      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
238      * or a positive value, the animation restarts from the beginning.
239      */
240     public static final int RESTART = 1;
241     /**
242      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
243      * or a positive value, the animation reverses direction on every iteration.
244      */
245     public static final int REVERSE = 2;
246     /**
247      * This value used used with the {@link #setRepeatCount(int)} property to repeat
248      * the animation indefinitely.
249      */
250     public static final int INFINITE = -1;
251 
252 
253     /**
254      * @hide
255      */
setDurationScale(float durationScale)256     public static void setDurationScale(float durationScale) {
257         sDurationScale = durationScale;
258     }
259 
260     /**
261      * @hide
262      */
getDurationScale()263     public static float getDurationScale() {
264         return sDurationScale;
265     }
266 
267     /**
268      * Creates a new ValueAnimator object. This default constructor is primarily for
269      * use internally; the factory methods which take parameters are more generally
270      * useful.
271      */
ValueAnimator()272     public ValueAnimator() {
273     }
274 
275     /**
276      * Constructs and returns a ValueAnimator that animates between int values. A single
277      * value implies that that value is the one being animated to. However, this is not typically
278      * useful in a ValueAnimator object because there is no way for the object to determine the
279      * starting value for the animation (unlike ObjectAnimator, which can derive that value
280      * from the target object and property being animated). Therefore, there should typically
281      * be two or more values.
282      *
283      * @param values A set of values that the animation will animate between over time.
284      * @return A ValueAnimator object that is set up to animate between the given values.
285      */
ofInt(int... values)286     public static ValueAnimator ofInt(int... values) {
287         ValueAnimator anim = new ValueAnimator();
288         anim.setIntValues(values);
289         return anim;
290     }
291 
292     /**
293      * Constructs and returns a ValueAnimator that animates between color values. A single
294      * value implies that that value is the one being animated to. However, this is not typically
295      * useful in a ValueAnimator object because there is no way for the object to determine the
296      * starting value for the animation (unlike ObjectAnimator, which can derive that value
297      * from the target object and property being animated). Therefore, there should typically
298      * be two or more values.
299      *
300      * @param values A set of values that the animation will animate between over time.
301      * @return A ValueAnimator object that is set up to animate between the given values.
302      */
ofArgb(int... values)303     public static ValueAnimator ofArgb(int... values) {
304         ValueAnimator anim = new ValueAnimator();
305         anim.setIntValues(values);
306         anim.setEvaluator(ArgbEvaluator.getInstance());
307         return anim;
308     }
309 
310     /**
311      * Constructs and returns a ValueAnimator that animates between float values. A single
312      * value implies that that value is the one being animated to. However, this is not typically
313      * useful in a ValueAnimator object because there is no way for the object to determine the
314      * starting value for the animation (unlike ObjectAnimator, which can derive that value
315      * from the target object and property being animated). Therefore, there should typically
316      * be two or more values.
317      *
318      * @param values A set of values that the animation will animate between over time.
319      * @return A ValueAnimator object that is set up to animate between the given values.
320      */
ofFloat(float... values)321     public static ValueAnimator ofFloat(float... values) {
322         ValueAnimator anim = new ValueAnimator();
323         anim.setFloatValues(values);
324         return anim;
325     }
326 
327     /**
328      * Constructs and returns a ValueAnimator that animates between the values
329      * specified in the PropertyValuesHolder objects.
330      *
331      * @param values A set of PropertyValuesHolder objects whose values will be animated
332      * between over time.
333      * @return A ValueAnimator object that is set up to animate between the given values.
334      */
ofPropertyValuesHolder(PropertyValuesHolder... values)335     public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
336         ValueAnimator anim = new ValueAnimator();
337         anim.setValues(values);
338         return anim;
339     }
340     /**
341      * Constructs and returns a ValueAnimator that animates between Object values. A single
342      * value implies that that value is the one being animated to. However, this is not typically
343      * useful in a ValueAnimator object because there is no way for the object to determine the
344      * starting value for the animation (unlike ObjectAnimator, which can derive that value
345      * from the target object and property being animated). Therefore, there should typically
346      * be two or more values.
347      *
348      * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
349      * factory method also takes a TypeEvaluator object that the ValueAnimator will use
350      * to perform that interpolation.
351      *
352      * @param evaluator A TypeEvaluator that will be called on each animation frame to
353      * provide the ncessry interpolation between the Object values to derive the animated
354      * value.
355      * @param values A set of values that the animation will animate between over time.
356      * @return A ValueAnimator object that is set up to animate between the given values.
357      */
ofObject(TypeEvaluator evaluator, Object... values)358     public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
359         ValueAnimator anim = new ValueAnimator();
360         anim.setObjectValues(values);
361         anim.setEvaluator(evaluator);
362         return anim;
363     }
364 
365     /**
366      * Sets int values that will be animated between. A single
367      * value implies that that value is the one being animated to. However, this is not typically
368      * useful in a ValueAnimator object because there is no way for the object to determine the
369      * starting value for the animation (unlike ObjectAnimator, which can derive that value
370      * from the target object and property being animated). Therefore, there should typically
371      * be two or more values.
372      *
373      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
374      * than one PropertyValuesHolder object, this method will set the values for the first
375      * of those objects.</p>
376      *
377      * @param values A set of values that the animation will animate between over time.
378      */
setIntValues(int... values)379     public void setIntValues(int... values) {
380         if (values == null || values.length == 0) {
381             return;
382         }
383         if (mValues == null || mValues.length == 0) {
384             setValues(PropertyValuesHolder.ofInt("", values));
385         } else {
386             PropertyValuesHolder valuesHolder = mValues[0];
387             valuesHolder.setIntValues(values);
388         }
389         // New property/values/target should cause re-initialization prior to starting
390         mInitialized = false;
391     }
392 
393     /**
394      * Sets float values that will be animated between. A single
395      * value implies that that value is the one being animated to. However, this is not typically
396      * useful in a ValueAnimator object because there is no way for the object to determine the
397      * starting value for the animation (unlike ObjectAnimator, which can derive that value
398      * from the target object and property being animated). Therefore, there should typically
399      * be two or more values.
400      *
401      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
402      * than one PropertyValuesHolder object, this method will set the values for the first
403      * of those objects.</p>
404      *
405      * @param values A set of values that the animation will animate between over time.
406      */
setFloatValues(float... values)407     public void setFloatValues(float... values) {
408         if (values == null || values.length == 0) {
409             return;
410         }
411         if (mValues == null || mValues.length == 0) {
412             setValues(PropertyValuesHolder.ofFloat("", values));
413         } else {
414             PropertyValuesHolder valuesHolder = mValues[0];
415             valuesHolder.setFloatValues(values);
416         }
417         // New property/values/target should cause re-initialization prior to starting
418         mInitialized = false;
419     }
420 
421     /**
422      * Sets the values to animate between for this animation. A single
423      * value implies that that value is the one being animated to. However, this is not typically
424      * useful in a ValueAnimator object because there is no way for the object to determine the
425      * starting value for the animation (unlike ObjectAnimator, which can derive that value
426      * from the target object and property being animated). Therefore, there should typically
427      * be two or more values.
428      *
429      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
430      * than one PropertyValuesHolder object, this method will set the values for the first
431      * of those objects.</p>
432      *
433      * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
434      * between these value objects. ValueAnimator only knows how to interpolate between the
435      * primitive types specified in the other setValues() methods.</p>
436      *
437      * @param values The set of values to animate between.
438      */
setObjectValues(Object... values)439     public void setObjectValues(Object... values) {
440         if (values == null || values.length == 0) {
441             return;
442         }
443         if (mValues == null || mValues.length == 0) {
444             setValues(PropertyValuesHolder.ofObject("", null, values));
445         } else {
446             PropertyValuesHolder valuesHolder = mValues[0];
447             valuesHolder.setObjectValues(values);
448         }
449         // New property/values/target should cause re-initialization prior to starting
450         mInitialized = false;
451     }
452 
453     /**
454      * Sets the values, per property, being animated between. This function is called internally
455      * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can
456      * be constructed without values and this method can be called to set the values manually
457      * instead.
458      *
459      * @param values The set of values, per property, being animated between.
460      */
setValues(PropertyValuesHolder... values)461     public void setValues(PropertyValuesHolder... values) {
462         int numValues = values.length;
463         mValues = values;
464         mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
465         for (int i = 0; i < numValues; ++i) {
466             PropertyValuesHolder valuesHolder = values[i];
467             mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
468         }
469         // New property/values/target should cause re-initialization prior to starting
470         mInitialized = false;
471     }
472 
473     /**
474      * Returns the values that this ValueAnimator animates between. These values are stored in
475      * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
476      * of value objects instead.
477      *
478      * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
479      * values, per property, that define the animation.
480      */
getValues()481     public PropertyValuesHolder[] getValues() {
482         return mValues;
483     }
484 
485     /**
486      * This function is called immediately before processing the first animation
487      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
488      * function is called after that delay ends.
489      * It takes care of the final initialization steps for the
490      * animation.
491      *
492      *  <p>Overrides of this method should call the superclass method to ensure
493      *  that internal mechanisms for the animation are set up correctly.</p>
494      */
initAnimation()495     void initAnimation() {
496         if (!mInitialized) {
497             int numValues = mValues.length;
498             for (int i = 0; i < numValues; ++i) {
499                 mValues[i].init();
500             }
501             mInitialized = true;
502         }
503     }
504 
505 
506     /**
507      * Sets the length of the animation. The default duration is 300 milliseconds.
508      *
509      * @param duration The length of the animation, in milliseconds. This value cannot
510      * be negative.
511      * @return ValueAnimator The object called with setDuration(). This return
512      * value makes it easier to compose statements together that construct and then set the
513      * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
514      */
setDuration(long duration)515     public ValueAnimator setDuration(long duration) {
516         if (duration < 0) {
517             throw new IllegalArgumentException("Animators cannot have negative duration: " +
518                     duration);
519         }
520         mUnscaledDuration = duration;
521         updateScaledDuration();
522         return this;
523     }
524 
updateScaledDuration()525     private void updateScaledDuration() {
526         mDuration = (long)(mUnscaledDuration * sDurationScale);
527     }
528 
529     /**
530      * Gets the length of the animation. The default duration is 300 milliseconds.
531      *
532      * @return The length of the animation, in milliseconds.
533      */
getDuration()534     public long getDuration() {
535         return mUnscaledDuration;
536     }
537 
538     /**
539      * Sets the position of the animation to the specified point in time. This time should
540      * be between 0 and the total duration of the animation, including any repetition. If
541      * the animation has not yet been started, then it will not advance forward after it is
542      * set to this time; it will simply set the time to this value and perform any appropriate
543      * actions based on that time. If the animation is already running, then setCurrentPlayTime()
544      * will set the current playing time to this value and continue playing from that point.
545      *
546      * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
547      */
setCurrentPlayTime(long playTime)548     public void setCurrentPlayTime(long playTime) {
549         float fraction = mUnscaledDuration > 0 ? (float) playTime / mUnscaledDuration : 1;
550         setCurrentFraction(fraction);
551     }
552 
553     /**
554      * Sets the position of the animation to the specified fraction. This fraction should
555      * be between 0 and the total fraction of the animation, including any repetition. That is,
556      * a fraction of 0 will position the animation at the beginning, a value of 1 at the end,
557      * and a value of 2 at the end of a reversing animator that repeats once. If
558      * the animation has not yet been started, then it will not advance forward after it is
559      * set to this fraction; it will simply set the fraction to this value and perform any
560      * appropriate actions based on that fraction. If the animation is already running, then
561      * setCurrentFraction() will set the current fraction to this value and continue
562      * playing from that point. {@link Animator.AnimatorListener} events are not called
563      * due to changing the fraction; those events are only processed while the animation
564      * is running.
565      *
566      * @param fraction The fraction to which the animation is advanced or rewound. Values
567      * outside the range of 0 to the maximum fraction for the animator will be clamped to
568      * the correct range.
569      */
setCurrentFraction(float fraction)570     public void setCurrentFraction(float fraction) {
571         initAnimation();
572         if (fraction < 0) {
573             fraction = 0;
574         }
575         int iteration = (int) fraction;
576         if (fraction == 1) {
577             iteration -= 1;
578         } else if (fraction > 1) {
579             if (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE) {
580                 if (mRepeatMode == REVERSE) {
581                     mPlayingBackwards = (iteration % 2) != 0;
582                 }
583                 fraction = fraction % 1f;
584             } else {
585                 fraction = 1;
586                 iteration -= 1;
587             }
588         } else {
589             mPlayingBackwards = mReversing;
590         }
591         mCurrentIteration = iteration;
592         long seekTime = (long) (mDuration * fraction);
593         long currentTime = AnimationUtils.currentAnimationTimeMillis();
594         mStartTime = currentTime - seekTime;
595         if (mPlayingState != RUNNING) {
596             mSeekFraction = fraction;
597             mPlayingState = SEEKED;
598         }
599         if (mPlayingBackwards) {
600             fraction = 1f - fraction;
601         }
602         animateValue(fraction);
603     }
604 
605     /**
606      * Gets the current position of the animation in time, which is equal to the current
607      * time minus the time that the animation started. An animation that is not yet started will
608      * return a value of zero.
609      *
610      * @return The current position in time of the animation.
611      */
getCurrentPlayTime()612     public long getCurrentPlayTime() {
613         if (!mInitialized || mPlayingState == STOPPED) {
614             return 0;
615         }
616         return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
617     }
618 
619     /**
620      * This custom, static handler handles the timing pulse that is shared by
621      * all active animations. This approach ensures that the setting of animation
622      * values will happen on the UI thread and that all animations will share
623      * the same times for calculating their values, which makes synchronizing
624      * animations possible.
625      *
626      * The handler uses the Choreographer for executing periodic callbacks.
627      *
628      * @hide
629      */
630     @SuppressWarnings("unchecked")
631     protected static class AnimationHandler implements Runnable {
632         // The per-thread list of all active animations
633         /** @hide */
634         protected final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
635 
636         // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
637         private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
638 
639         // The per-thread set of animations to be started on the next animation frame
640         /** @hide */
641         protected final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
642 
643         /**
644          * Internal per-thread collections used to avoid set collisions as animations start and end
645          * while being processed.
646          * @hide
647          */
648         protected final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
649         private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
650         private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
651 
652         private final Choreographer mChoreographer;
653         private boolean mAnimationScheduled;
654 
AnimationHandler()655         private AnimationHandler() {
656             mChoreographer = Choreographer.getInstance();
657         }
658 
659         /**
660          * Start animating on the next frame.
661          */
start()662         public void start() {
663             scheduleAnimation();
664         }
665 
doAnimationFrame(long frameTime)666         private void doAnimationFrame(long frameTime) {
667             // mPendingAnimations holds any animations that have requested to be started
668             // We're going to clear mPendingAnimations, but starting animation may
669             // cause more to be added to the pending list (for example, if one animation
670             // starting triggers another starting). So we loop until mPendingAnimations
671             // is empty.
672             while (mPendingAnimations.size() > 0) {
673                 ArrayList<ValueAnimator> pendingCopy =
674                         (ArrayList<ValueAnimator>) mPendingAnimations.clone();
675                 mPendingAnimations.clear();
676                 int count = pendingCopy.size();
677                 for (int i = 0; i < count; ++i) {
678                     ValueAnimator anim = pendingCopy.get(i);
679                     // If the animation has a startDelay, place it on the delayed list
680                     if (anim.mStartDelay == 0) {
681                         anim.startAnimation(this);
682                     } else {
683                         mDelayedAnims.add(anim);
684                     }
685                 }
686             }
687             // Next, process animations currently sitting on the delayed queue, adding
688             // them to the active animations if they are ready
689             int numDelayedAnims = mDelayedAnims.size();
690             for (int i = 0; i < numDelayedAnims; ++i) {
691                 ValueAnimator anim = mDelayedAnims.get(i);
692                 if (anim.delayedAnimationFrame(frameTime)) {
693                     mReadyAnims.add(anim);
694                 }
695             }
696             int numReadyAnims = mReadyAnims.size();
697             if (numReadyAnims > 0) {
698                 for (int i = 0; i < numReadyAnims; ++i) {
699                     ValueAnimator anim = mReadyAnims.get(i);
700                     anim.startAnimation(this);
701                     anim.mRunning = true;
702                     mDelayedAnims.remove(anim);
703                 }
704                 mReadyAnims.clear();
705             }
706 
707             // Now process all active animations. The return value from animationFrame()
708             // tells the handler whether it should now be ended
709             int numAnims = mAnimations.size();
710             for (int i = 0; i < numAnims; ++i) {
711                 mTmpAnimations.add(mAnimations.get(i));
712             }
713             for (int i = 0; i < numAnims; ++i) {
714                 ValueAnimator anim = mTmpAnimations.get(i);
715                 if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
716                     mEndingAnims.add(anim);
717                 }
718             }
719             mTmpAnimations.clear();
720             if (mEndingAnims.size() > 0) {
721                 for (int i = 0; i < mEndingAnims.size(); ++i) {
722                     mEndingAnims.get(i).endAnimation(this);
723                 }
724                 mEndingAnims.clear();
725             }
726 
727             // If there are still active or delayed animations, schedule a future call to
728             // onAnimate to process the next frame of the animations.
729             if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
730                 scheduleAnimation();
731             }
732         }
733 
734         // Called by the Choreographer.
735         @Override
run()736         public void run() {
737             mAnimationScheduled = false;
738             doAnimationFrame(mChoreographer.getFrameTime());
739         }
740 
scheduleAnimation()741         private void scheduleAnimation() {
742             if (!mAnimationScheduled) {
743                 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
744                 mAnimationScheduled = true;
745             }
746         }
747     }
748 
749     /**
750      * The amount of time, in milliseconds, to delay starting the animation after
751      * {@link #start()} is called.
752      *
753      * @return the number of milliseconds to delay running the animation
754      */
getStartDelay()755     public long getStartDelay() {
756         return mUnscaledStartDelay;
757     }
758 
759     /**
760      * The amount of time, in milliseconds, to delay starting the animation after
761      * {@link #start()} is called.
762 
763      * @param startDelay The amount of the delay, in milliseconds
764      */
setStartDelay(long startDelay)765     public void setStartDelay(long startDelay) {
766         this.mStartDelay = (long)(startDelay * sDurationScale);
767         mUnscaledStartDelay = startDelay;
768     }
769 
770     /**
771      * The amount of time, in milliseconds, between each frame of the animation. This is a
772      * requested time that the animation will attempt to honor, but the actual delay between
773      * frames may be different, depending on system load and capabilities. This is a static
774      * function because the same delay will be applied to all animations, since they are all
775      * run off of a single timing loop.
776      *
777      * The frame delay may be ignored when the animation system uses an external timing
778      * source, such as the display refresh rate (vsync), to govern animations.
779      *
780      * @return the requested time between frames, in milliseconds
781      */
getFrameDelay()782     public static long getFrameDelay() {
783         return Choreographer.getFrameDelay();
784     }
785 
786     /**
787      * The amount of time, in milliseconds, between each frame of the animation. This is a
788      * requested time that the animation will attempt to honor, but the actual delay between
789      * frames may be different, depending on system load and capabilities. This is a static
790      * function because the same delay will be applied to all animations, since they are all
791      * run off of a single timing loop.
792      *
793      * The frame delay may be ignored when the animation system uses an external timing
794      * source, such as the display refresh rate (vsync), to govern animations.
795      *
796      * @param frameDelay the requested time between frames, in milliseconds
797      */
setFrameDelay(long frameDelay)798     public static void setFrameDelay(long frameDelay) {
799         Choreographer.setFrameDelay(frameDelay);
800     }
801 
802     /**
803      * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
804      * property being animated. This value is only sensible while the animation is running. The main
805      * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
806      * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
807      * is called during each animation frame, immediately after the value is calculated.
808      *
809      * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
810      * the single property being animated. If there are several properties being animated
811      * (specified by several PropertyValuesHolder objects in the constructor), this function
812      * returns the animated value for the first of those objects.
813      */
getAnimatedValue()814     public Object getAnimatedValue() {
815         if (mValues != null && mValues.length > 0) {
816             return mValues[0].getAnimatedValue();
817         }
818         // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
819         return null;
820     }
821 
822     /**
823      * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
824      * The main purpose for this read-only property is to retrieve the value from the
825      * <code>ValueAnimator</code> during a call to
826      * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
827      * is called during each animation frame, immediately after the value is calculated.
828      *
829      * @return animatedValue The value most recently calculated for the named property
830      * by this <code>ValueAnimator</code>.
831      */
getAnimatedValue(String propertyName)832     public Object getAnimatedValue(String propertyName) {
833         PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
834         if (valuesHolder != null) {
835             return valuesHolder.getAnimatedValue();
836         } else {
837             // At least avoid crashing if called with bogus propertyName
838             return null;
839         }
840     }
841 
842     /**
843      * Sets how many times the animation should be repeated. If the repeat
844      * count is 0, the animation is never repeated. If the repeat count is
845      * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
846      * into account. The repeat count is 0 by default.
847      *
848      * @param value the number of times the animation should be repeated
849      */
setRepeatCount(int value)850     public void setRepeatCount(int value) {
851         mRepeatCount = value;
852     }
853     /**
854      * Defines how many times the animation should repeat. The default value
855      * is 0.
856      *
857      * @return the number of times the animation should repeat, or {@link #INFINITE}
858      */
getRepeatCount()859     public int getRepeatCount() {
860         return mRepeatCount;
861     }
862 
863     /**
864      * Defines what this animation should do when it reaches the end. This
865      * setting is applied only when the repeat count is either greater than
866      * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
867      *
868      * @param value {@link #RESTART} or {@link #REVERSE}
869      */
setRepeatMode(int value)870     public void setRepeatMode(int value) {
871         mRepeatMode = value;
872     }
873 
874     /**
875      * Defines what this animation should do when it reaches the end.
876      *
877      * @return either one of {@link #REVERSE} or {@link #RESTART}
878      */
getRepeatMode()879     public int getRepeatMode() {
880         return mRepeatMode;
881     }
882 
883     /**
884      * Adds a listener to the set of listeners that are sent update events through the life of
885      * an animation. This method is called on all listeners for every frame of the animation,
886      * after the values for the animation have been calculated.
887      *
888      * @param listener the listener to be added to the current set of listeners for this animation.
889      */
addUpdateListener(AnimatorUpdateListener listener)890     public void addUpdateListener(AnimatorUpdateListener listener) {
891         if (mUpdateListeners == null) {
892             mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
893         }
894         mUpdateListeners.add(listener);
895     }
896 
897     /**
898      * Removes all listeners from the set listening to frame updates for this animation.
899      */
removeAllUpdateListeners()900     public void removeAllUpdateListeners() {
901         if (mUpdateListeners == null) {
902             return;
903         }
904         mUpdateListeners.clear();
905         mUpdateListeners = null;
906     }
907 
908     /**
909      * Removes a listener from the set listening to frame updates for this animation.
910      *
911      * @param listener the listener to be removed from the current set of update listeners
912      * for this animation.
913      */
removeUpdateListener(AnimatorUpdateListener listener)914     public void removeUpdateListener(AnimatorUpdateListener listener) {
915         if (mUpdateListeners == null) {
916             return;
917         }
918         mUpdateListeners.remove(listener);
919         if (mUpdateListeners.size() == 0) {
920             mUpdateListeners = null;
921         }
922     }
923 
924 
925     /**
926      * The time interpolator used in calculating the elapsed fraction of this animation. The
927      * interpolator determines whether the animation runs with linear or non-linear motion,
928      * such as acceleration and deceleration. The default value is
929      * {@link android.view.animation.AccelerateDecelerateInterpolator}
930      *
931      * @param value the interpolator to be used by this animation. A value of <code>null</code>
932      * will result in linear interpolation.
933      */
934     @Override
setInterpolator(TimeInterpolator value)935     public void setInterpolator(TimeInterpolator value) {
936         if (value != null) {
937             mInterpolator = value;
938         } else {
939             mInterpolator = new LinearInterpolator();
940         }
941     }
942 
943     /**
944      * Returns the timing interpolator that this ValueAnimator uses.
945      *
946      * @return The timing interpolator for this ValueAnimator.
947      */
948     @Override
getInterpolator()949     public TimeInterpolator getInterpolator() {
950         return mInterpolator;
951     }
952 
953     /**
954      * The type evaluator to be used when calculating the animated values of this animation.
955      * The system will automatically assign a float or int evaluator based on the type
956      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
957      * are not one of these primitive types, or if different evaluation is desired (such as is
958      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
959      * For example, when running an animation on color values, the {@link ArgbEvaluator}
960      * should be used to get correct RGB color interpolation.
961      *
962      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
963      * will be used for that set. If there are several sets of values being animated, which is
964      * the case if PropertyValuesHolder objects were set on the ValueAnimator, then the evaluator
965      * is assigned just to the first PropertyValuesHolder object.</p>
966      *
967      * @param value the evaluator to be used this animation
968      */
setEvaluator(TypeEvaluator value)969     public void setEvaluator(TypeEvaluator value) {
970         if (value != null && mValues != null && mValues.length > 0) {
971             mValues[0].setEvaluator(value);
972         }
973     }
974 
notifyStartListeners()975     private void notifyStartListeners() {
976         if (mListeners != null && !mStartListenersCalled) {
977             ArrayList<AnimatorListener> tmpListeners =
978                     (ArrayList<AnimatorListener>) mListeners.clone();
979             int numListeners = tmpListeners.size();
980             for (int i = 0; i < numListeners; ++i) {
981                 tmpListeners.get(i).onAnimationStart(this);
982             }
983         }
984         mStartListenersCalled = true;
985     }
986 
987     /**
988      * Start the animation playing. This version of start() takes a boolean flag that indicates
989      * whether the animation should play in reverse. The flag is usually false, but may be set
990      * to true if called from the reverse() method.
991      *
992      * <p>The animation started by calling this method will be run on the thread that called
993      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
994      * this is not the case). Also, if the animation will animate
995      * properties of objects in the view hierarchy, then the calling thread should be the UI
996      * thread for that view hierarchy.</p>
997      *
998      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
999      */
start(boolean playBackwards)1000     private void start(boolean playBackwards) {
1001         if (Looper.myLooper() == null) {
1002             throw new AndroidRuntimeException("Animators may only be run on Looper threads");
1003         }
1004         mReversing = playBackwards;
1005         mPlayingBackwards = playBackwards;
1006         if (playBackwards && mSeekFraction != -1) {
1007             if (mSeekFraction == 0 && mCurrentIteration == 0) {
1008                 // special case: reversing from seek-to-0 should act as if not seeked at all
1009                 mSeekFraction = 0;
1010             } else if (mRepeatCount == INFINITE) {
1011                 mSeekFraction = 1 - (mSeekFraction % 1);
1012             } else {
1013                 mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);
1014             }
1015             mCurrentIteration = (int) mSeekFraction;
1016             mSeekFraction = mSeekFraction % 1;
1017         }
1018         if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&
1019                 (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
1020             // if we were seeked to some other iteration in a reversing animator,
1021             // figure out the correct direction to start playing based on the iteration
1022             if (playBackwards) {
1023                 mPlayingBackwards = (mCurrentIteration % 2) == 0;
1024             } else {
1025                 mPlayingBackwards = (mCurrentIteration % 2) != 0;
1026             }
1027         }
1028         int prevPlayingState = mPlayingState;
1029         mPlayingState = STOPPED;
1030         mStarted = true;
1031         mStartedDelay = false;
1032         mPaused = false;
1033         updateScaledDuration(); // in case the scale factor has changed since creation time
1034         AnimationHandler animationHandler = getOrCreateAnimationHandler();
1035         animationHandler.mPendingAnimations.add(this);
1036         if (mStartDelay == 0) {
1037             // This sets the initial value of the animation, prior to actually starting it running
1038             if (prevPlayingState != SEEKED) {
1039                 setCurrentPlayTime(0);
1040             }
1041             mPlayingState = STOPPED;
1042             mRunning = true;
1043             notifyStartListeners();
1044         }
1045         animationHandler.start();
1046     }
1047 
1048     @Override
start()1049     public void start() {
1050         start(false);
1051     }
1052 
1053     @Override
cancel()1054     public void cancel() {
1055         // Only cancel if the animation is actually running or has been started and is about
1056         // to run
1057         AnimationHandler handler = getOrCreateAnimationHandler();
1058         if (mPlayingState != STOPPED
1059                 || handler.mPendingAnimations.contains(this)
1060                 || handler.mDelayedAnims.contains(this)) {
1061             // Only notify listeners if the animator has actually started
1062             if ((mStarted || mRunning) && mListeners != null) {
1063                 if (!mRunning) {
1064                     // If it's not yet running, then start listeners weren't called. Call them now.
1065                     notifyStartListeners();
1066                 }
1067                 ArrayList<AnimatorListener> tmpListeners =
1068                         (ArrayList<AnimatorListener>) mListeners.clone();
1069                 for (AnimatorListener listener : tmpListeners) {
1070                     listener.onAnimationCancel(this);
1071                 }
1072             }
1073             endAnimation(handler);
1074         }
1075     }
1076 
1077     @Override
end()1078     public void end() {
1079         AnimationHandler handler = getOrCreateAnimationHandler();
1080         if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
1081             // Special case if the animation has not yet started; get it ready for ending
1082             mStartedDelay = false;
1083             startAnimation(handler);
1084             mStarted = true;
1085         } else if (!mInitialized) {
1086             initAnimation();
1087         }
1088         animateValue(mPlayingBackwards ? 0f : 1f);
1089         endAnimation(handler);
1090     }
1091 
1092     @Override
resume()1093     public void resume() {
1094         if (mPaused) {
1095             mResumed = true;
1096         }
1097         super.resume();
1098     }
1099 
1100     @Override
pause()1101     public void pause() {
1102         boolean previouslyPaused = mPaused;
1103         super.pause();
1104         if (!previouslyPaused && mPaused) {
1105             mPauseTime = -1;
1106             mResumed = false;
1107         }
1108     }
1109 
1110     @Override
isRunning()1111     public boolean isRunning() {
1112         return (mPlayingState == RUNNING || mRunning);
1113     }
1114 
1115     @Override
isStarted()1116     public boolean isStarted() {
1117         return mStarted;
1118     }
1119 
1120     /**
1121      * Plays the ValueAnimator in reverse. If the animation is already running,
1122      * it will stop itself and play backwards from the point reached when reverse was called.
1123      * If the animation is not currently running, then it will start from the end and
1124      * play backwards. This behavior is only set for the current animation; future playing
1125      * of the animation will use the default behavior of playing forward.
1126      */
1127     @Override
reverse()1128     public void reverse() {
1129         mPlayingBackwards = !mPlayingBackwards;
1130         if (mPlayingState == RUNNING) {
1131             long currentTime = AnimationUtils.currentAnimationTimeMillis();
1132             long currentPlayTime = currentTime - mStartTime;
1133             long timeLeft = mDuration - currentPlayTime;
1134             mStartTime = currentTime - timeLeft;
1135             mReversing = !mReversing;
1136         } else if (mStarted) {
1137             end();
1138         } else {
1139             start(true);
1140         }
1141     }
1142 
1143     /**
1144      * @hide
1145      */
1146     @Override
canReverse()1147     public boolean canReverse() {
1148         return true;
1149     }
1150 
1151     /**
1152      * Called internally to end an animation by removing it from the animations list. Must be
1153      * called on the UI thread.
1154      * @hide
1155      */
endAnimation(AnimationHandler handler)1156     protected void endAnimation(AnimationHandler handler) {
1157         handler.mAnimations.remove(this);
1158         handler.mPendingAnimations.remove(this);
1159         handler.mDelayedAnims.remove(this);
1160         mPlayingState = STOPPED;
1161         mPaused = false;
1162         if ((mStarted || mRunning) && mListeners != null) {
1163             if (!mRunning) {
1164                 // If it's not yet running, then start listeners weren't called. Call them now.
1165                 notifyStartListeners();
1166              }
1167             ArrayList<AnimatorListener> tmpListeners =
1168                     (ArrayList<AnimatorListener>) mListeners.clone();
1169             int numListeners = tmpListeners.size();
1170             for (int i = 0; i < numListeners; ++i) {
1171                 tmpListeners.get(i).onAnimationEnd(this);
1172             }
1173         }
1174         mRunning = false;
1175         mStarted = false;
1176         mStartListenersCalled = false;
1177         mPlayingBackwards = false;
1178         mReversing = false;
1179         mCurrentIteration = 0;
1180         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
1181             Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
1182                     System.identityHashCode(this));
1183         }
1184     }
1185 
1186     /**
1187      * Called internally to start an animation by adding it to the active animations list. Must be
1188      * called on the UI thread.
1189      */
startAnimation(AnimationHandler handler)1190     private void startAnimation(AnimationHandler handler) {
1191         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
1192             Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
1193                     System.identityHashCode(this));
1194         }
1195         initAnimation();
1196         handler.mAnimations.add(this);
1197         if (mStartDelay > 0 && mListeners != null) {
1198             // Listeners were already notified in start() if startDelay is 0; this is
1199             // just for delayed animations
1200             notifyStartListeners();
1201         }
1202     }
1203 
1204     /**
1205      * Returns the name of this animator for debugging purposes.
1206      */
getNameForTrace()1207     String getNameForTrace() {
1208         return "animator";
1209     }
1210 
1211 
1212     /**
1213      * Internal function called to process an animation frame on an animation that is currently
1214      * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
1215      * should be woken up and put on the active animations queue.
1216      *
1217      * @param currentTime The current animation time, used to calculate whether the animation
1218      * has exceeded its <code>startDelay</code> and should be started.
1219      * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
1220      * should be added to the set of active animations.
1221      */
delayedAnimationFrame(long currentTime)1222     private boolean delayedAnimationFrame(long currentTime) {
1223         if (!mStartedDelay) {
1224             mStartedDelay = true;
1225             mDelayStartTime = currentTime;
1226         }
1227         if (mPaused) {
1228             if (mPauseTime < 0) {
1229                 mPauseTime = currentTime;
1230             }
1231             return false;
1232         } else if (mResumed) {
1233             mResumed = false;
1234             if (mPauseTime > 0) {
1235                 // Offset by the duration that the animation was paused
1236                 mDelayStartTime += (currentTime - mPauseTime);
1237             }
1238         }
1239         long deltaTime = currentTime - mDelayStartTime;
1240         if (deltaTime > mStartDelay) {
1241             // startDelay ended - start the anim and record the
1242             // mStartTime appropriately
1243             mStartTime = currentTime - (deltaTime - mStartDelay);
1244             mPlayingState = RUNNING;
1245             return true;
1246         }
1247         return false;
1248     }
1249 
1250     /**
1251      * This internal function processes a single animation frame for a given animation. The
1252      * currentTime parameter is the timing pulse sent by the handler, used to calculate the
1253      * elapsed duration, and therefore
1254      * the elapsed fraction, of the animation. The return value indicates whether the animation
1255      * should be ended (which happens when the elapsed time of the animation exceeds the
1256      * animation's duration, including the repeatCount).
1257      *
1258      * @param currentTime The current time, as tracked by the static timing handler
1259      * @return true if the animation's duration, including any repetitions due to
1260      * <code>repeatCount</code>, has been exceeded and the animation should be ended.
1261      */
animationFrame(long currentTime)1262     boolean animationFrame(long currentTime) {
1263         boolean done = false;
1264         switch (mPlayingState) {
1265         case RUNNING:
1266         case SEEKED:
1267             float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
1268             if (mDuration == 0 && mRepeatCount != INFINITE) {
1269                 // Skip to the end
1270                 mCurrentIteration = mRepeatCount;
1271                 if (!mReversing) {
1272                     mPlayingBackwards = false;
1273                 }
1274             }
1275             if (fraction >= 1f) {
1276                 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
1277                     // Time to repeat
1278                     if (mListeners != null) {
1279                         int numListeners = mListeners.size();
1280                         for (int i = 0; i < numListeners; ++i) {
1281                             mListeners.get(i).onAnimationRepeat(this);
1282                         }
1283                     }
1284                     if (mRepeatMode == REVERSE) {
1285                         mPlayingBackwards = !mPlayingBackwards;
1286                     }
1287                     mCurrentIteration += (int) fraction;
1288                     fraction = fraction % 1f;
1289                     mStartTime += mDuration;
1290                 } else {
1291                     done = true;
1292                     fraction = Math.min(fraction, 1.0f);
1293                 }
1294             }
1295             if (mPlayingBackwards) {
1296                 fraction = 1f - fraction;
1297             }
1298             animateValue(fraction);
1299             break;
1300         }
1301 
1302         return done;
1303     }
1304 
1305     /**
1306      * Processes a frame of the animation, adjusting the start time if needed.
1307      *
1308      * @param frameTime The frame time.
1309      * @return true if the animation has ended.
1310      */
doAnimationFrame(long frameTime)1311     final boolean doAnimationFrame(long frameTime) {
1312         if (mPlayingState == STOPPED) {
1313             mPlayingState = RUNNING;
1314             if (mSeekFraction < 0) {
1315                 mStartTime = frameTime;
1316             } else {
1317                 long seekTime = (long) (mDuration * mSeekFraction);
1318                 mStartTime = frameTime - seekTime;
1319                 mSeekFraction = -1;
1320             }
1321         }
1322         if (mPaused) {
1323             if (mPauseTime < 0) {
1324                 mPauseTime = frameTime;
1325             }
1326             return false;
1327         } else if (mResumed) {
1328             mResumed = false;
1329             if (mPauseTime > 0) {
1330                 // Offset by the duration that the animation was paused
1331                 mStartTime += (frameTime - mPauseTime);
1332             }
1333         }
1334         // The frame time might be before the start time during the first frame of
1335         // an animation.  The "current time" must always be on or after the start
1336         // time to avoid animating frames at negative time intervals.  In practice, this
1337         // is very rare and only happens when seeking backwards.
1338         final long currentTime = Math.max(frameTime, mStartTime);
1339         return animationFrame(currentTime);
1340     }
1341 
1342     /**
1343      * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
1344      * the most recent frame update on the animation.
1345      *
1346      * @return Elapsed/interpolated fraction of the animation.
1347      */
getAnimatedFraction()1348     public float getAnimatedFraction() {
1349         return mCurrentFraction;
1350     }
1351 
1352     /**
1353      * This method is called with the elapsed fraction of the animation during every
1354      * animation frame. This function turns the elapsed fraction into an interpolated fraction
1355      * and then into an animated value (from the evaluator. The function is called mostly during
1356      * animation updates, but it is also called when the <code>end()</code>
1357      * function is called, to set the final value on the property.
1358      *
1359      * <p>Overrides of this method must call the superclass to perform the calculation
1360      * of the animated value.</p>
1361      *
1362      * @param fraction The elapsed fraction of the animation.
1363      */
animateValue(float fraction)1364     void animateValue(float fraction) {
1365         fraction = mInterpolator.getInterpolation(fraction);
1366         mCurrentFraction = fraction;
1367         int numValues = mValues.length;
1368         for (int i = 0; i < numValues; ++i) {
1369             mValues[i].calculateValue(fraction);
1370         }
1371         if (mUpdateListeners != null) {
1372             int numListeners = mUpdateListeners.size();
1373             for (int i = 0; i < numListeners; ++i) {
1374                 mUpdateListeners.get(i).onAnimationUpdate(this);
1375             }
1376         }
1377     }
1378 
1379     @Override
clone()1380     public ValueAnimator clone() {
1381         final ValueAnimator anim = (ValueAnimator) super.clone();
1382         if (mUpdateListeners != null) {
1383             anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
1384         }
1385         anim.mSeekFraction = -1;
1386         anim.mPlayingBackwards = false;
1387         anim.mReversing = false;
1388         anim.mCurrentIteration = 0;
1389         anim.mInitialized = false;
1390         anim.mPlayingState = STOPPED;
1391         anim.mStartedDelay = false;
1392         PropertyValuesHolder[] oldValues = mValues;
1393         if (oldValues != null) {
1394             int numValues = oldValues.length;
1395             anim.mValues = new PropertyValuesHolder[numValues];
1396             anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
1397             for (int i = 0; i < numValues; ++i) {
1398                 PropertyValuesHolder newValuesHolder = oldValues[i].clone();
1399                 anim.mValues[i] = newValuesHolder;
1400                 anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
1401             }
1402         }
1403         return anim;
1404     }
1405 
1406     /**
1407      * Implementors of this interface can add themselves as update listeners
1408      * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
1409      * frame, after the current frame's values have been calculated for that
1410      * <code>ValueAnimator</code>.
1411      */
1412     public static interface AnimatorUpdateListener {
1413         /**
1414          * <p>Notifies the occurrence of another frame of the animation.</p>
1415          *
1416          * @param animation The animation which was repeated.
1417          */
onAnimationUpdate(ValueAnimator animation)1418         void onAnimationUpdate(ValueAnimator animation);
1419 
1420     }
1421 
1422     /**
1423      * Return the number of animations currently running.
1424      *
1425      * Used by StrictMode internally to annotate violations.
1426      * May be called on arbitrary threads!
1427      *
1428      * @hide
1429      */
getCurrentAnimationsCount()1430     public static int getCurrentAnimationsCount() {
1431         AnimationHandler handler = sAnimationHandler.get();
1432         return handler != null ? handler.mAnimations.size() : 0;
1433     }
1434 
1435     /**
1436      * Clear all animations on this thread, without canceling or ending them.
1437      * This should be used with caution.
1438      *
1439      * @hide
1440      */
clearAllAnimations()1441     public static void clearAllAnimations() {
1442         AnimationHandler handler = sAnimationHandler.get();
1443         if (handler != null) {
1444             handler.mAnimations.clear();
1445             handler.mPendingAnimations.clear();
1446             handler.mDelayedAnims.clear();
1447         }
1448     }
1449 
getOrCreateAnimationHandler()1450     private static AnimationHandler getOrCreateAnimationHandler() {
1451         AnimationHandler handler = sAnimationHandler.get();
1452         if (handler == null) {
1453             handler = new AnimationHandler();
1454             sAnimationHandler.set(handler);
1455         }
1456         return handler;
1457     }
1458 
1459     @Override
toString()1460     public String toString() {
1461         String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
1462         if (mValues != null) {
1463             for (int i = 0; i < mValues.length; ++i) {
1464                 returnVal += "\n    " + mValues[i].toString();
1465             }
1466         }
1467         return returnVal;
1468     }
1469 
1470     /**
1471      * <p>Whether or not the ValueAnimator is allowed to run asynchronously off of
1472      * the UI thread. This is a hint that informs the ValueAnimator that it is
1473      * OK to run the animation off-thread, however ValueAnimator may decide
1474      * that it must run the animation on the UI thread anyway. For example if there
1475      * is an {@link AnimatorUpdateListener} the animation will run on the UI thread,
1476      * regardless of the value of this hint.</p>
1477      *
1478      * <p>Regardless of whether or not the animation runs asynchronously, all
1479      * listener callbacks will be called on the UI thread.</p>
1480      *
1481      * <p>To be able to use this hint the following must be true:</p>
1482      * <ol>
1483      * <li>{@link #getAnimatedFraction()} is not needed (it will return undefined values).</li>
1484      * <li>The animator is immutable while {@link #isStarted()} is true. Requests
1485      *    to change values, duration, delay, etc... may be ignored.</li>
1486      * <li>Lifecycle callback events may be asynchronous. Events such as
1487      *    {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or
1488      *    {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed
1489      *    as they must be posted back to the UI thread, and any actions performed
1490      *    by those callbacks (such as starting new animations) will not happen
1491      *    in the same frame.</li>
1492      * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...)
1493      *    may be asynchronous. It is guaranteed that all state changes that are
1494      *    performed on the UI thread in the same frame will be applied as a single
1495      *    atomic update, however that frame may be the current frame,
1496      *    the next frame, or some future frame. This will also impact the observed
1497      *    state of the Animator. For example, {@link #isStarted()} may still return true
1498      *    after a call to {@link #end()}. Using the lifecycle callbacks is preferred over
1499      *    queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()}
1500      *    for this reason.</li>
1501      * </ol>
1502      * @hide
1503      */
1504     @Override
setAllowRunningAsynchronously(boolean mayRunAsync)1505     public void setAllowRunningAsynchronously(boolean mayRunAsync) {
1506         // It is up to subclasses to support this, if they can.
1507     }
1508 }
1509