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