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