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