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