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