• 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.os.Handler;
20 import android.os.Looper;
21 import android.os.Message;
22 import android.os.SystemProperties;
23 import android.util.AndroidRuntimeException;
24 import android.view.Choreographer;
25 import android.view.animation.AccelerateDecelerateInterpolator;
26 import android.view.animation.AnimationUtils;
27 import android.view.animation.LinearInterpolator;
28 
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 
32 /**
33  * This class provides a simple timing engine for running animations
34  * which calculate animated values and set them on target objects.
35  *
36  * <p>There is a single timing pulse that all animations use. It runs in a
37  * custom handler to ensure that property changes happen on the UI thread.</p>
38  *
39  * <p>By default, ValueAnimator uses non-linear time interpolation, via the
40  * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
41  * out of an animation. This behavior can be changed by calling
42  * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
43  *
44  * <div class="special reference">
45  * <h3>Developer Guides</h3>
46  * <p>For more information about animating with {@code ValueAnimator}, read the
47  * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property
48  * Animation</a> developer guide.</p>
49  * </div>
50  */
51 public class ValueAnimator extends Animator {
52 
53     /**
54      * Internal constants
55      */
56     private static float sDurationScale = 1.0f;
57 
58     /**
59      * Values used with internal variable mPlayingState to indicate the current state of an
60      * animation.
61      */
62     static final int STOPPED    = 0; // Not yet playing
63     static final int RUNNING    = 1; // Playing normally
64     static final int SEEKED     = 2; // Seeked to some time value
65 
66     /**
67      * Internal variables
68      * NOTE: This object implements the clone() method, making a deep copy of any referenced
69      * objects. As other non-trivial fields are added to this class, make sure to add logic
70      * to clone() to make deep copies of them.
71      */
72 
73     // The first time that the animation's animateFrame() method is called. This time is used to
74     // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
75     // to animateFrame()
76     long mStartTime;
77 
78     /**
79      * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
80      * to a value.
81      */
82     long mSeekTime = -1;
83 
84     // The static sAnimationHandler processes the internal timing loop on which all animations
85     // are based
86     private static ThreadLocal<AnimationHandler> sAnimationHandler =
87             new ThreadLocal<AnimationHandler>();
88 
89     // The time interpolator to be used if none is set on the animation
90     private static final TimeInterpolator sDefaultInterpolator =
91             new AccelerateDecelerateInterpolator();
92 
93     /**
94      * Used to indicate whether the animation is currently playing in reverse. This causes the
95      * elapsed fraction to be inverted to calculate the appropriate values.
96      */
97     private boolean mPlayingBackwards = false;
98 
99     /**
100      * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
101      * repeatCount (if repeatCount!=INFINITE), the animation ends
102      */
103     private int mCurrentIteration = 0;
104 
105     /**
106      * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
107      */
108     private float mCurrentFraction = 0f;
109 
110     /**
111      * Tracks whether a startDelay'd animation has begun playing through the startDelay.
112      */
113     private boolean mStartedDelay = false;
114 
115     /**
116      * Tracks the time at which the animation began playing through its startDelay. This is
117      * different from the mStartTime variable, which is used to track when the animation became
118      * active (which is when the startDelay expired and the animation was added to the active
119      * animations list).
120      */
121     private long mDelayStartTime;
122 
123     /**
124      * Flag that represents the current state of the animation. Used to figure out when to start
125      * an animation (if state == STOPPED). Also used to end an animation that
126      * has been cancel()'d or end()'d since the last animation frame. Possible values are
127      * STOPPED, RUNNING, SEEKED.
128      */
129     int mPlayingState = STOPPED;
130 
131     /**
132      * Additional playing state to indicate whether an animator has been start()'d. There is
133      * some lag between a call to start() and the first animation frame. We should still note
134      * that the animation has been started, even if it's first animation frame has not yet
135      * happened, and reflect that state in isRunning().
136      * Note that delayed animations are different: they are not started until their first
137      * animation frame, which occurs after their delay elapses.
138      */
139     private boolean mRunning = false;
140 
141     /**
142      * Additional playing state to indicate whether an animator has been start()'d, whether or
143      * not there is a nonzero startDelay.
144      */
145     private boolean mStarted = false;
146 
147     /**
148      * Tracks whether we've notified listeners of the onAnimationSTart() event. This can be
149      * complex to keep track of since we notify listeners at different times depending on
150      * startDelay and whether start() was called before end().
151      */
152     private boolean mStartListenersCalled = false;
153 
154     /**
155      * Flag that denotes whether the animation is set up and ready to go. Used to
156      * set up animation that has not yet been started.
157      */
158     boolean mInitialized = false;
159 
160     //
161     // Backing variables
162     //
163 
164     // How long the animation should last in ms
165     private long mDuration = (long)(300 * sDurationScale);
166     private long mUnscaledDuration = 300;
167 
168     // The amount of time in ms to delay starting the animation after start() is called
169     private long mStartDelay = 0;
170     private long mUnscaledStartDelay = 0;
171 
172     // The number of times the animation will repeat. The default is 0, which means the animation
173     // will play only once
174     private int mRepeatCount = 0;
175 
176     /**
177      * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
178      * animation will start from the beginning on every new cycle. REVERSE means the animation
179      * will reverse directions on each iteration.
180      */
181     private int mRepeatMode = RESTART;
182 
183     /**
184      * The time interpolator to be used. The elapsed fraction of the animation will be passed
185      * through this interpolator to calculate the interpolated fraction, which is then used to
186      * calculate the animated values.
187      */
188     private TimeInterpolator mInterpolator = sDefaultInterpolator;
189 
190     /**
191      * The set of listeners to be sent events through the life of an animation.
192      */
193     private ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
194 
195     /**
196      * The property/value sets being animated.
197      */
198     PropertyValuesHolder[] mValues;
199 
200     /**
201      * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
202      * by property name during calls to getAnimatedValue(String).
203      */
204     HashMap<String, PropertyValuesHolder> mValuesMap;
205 
206     /**
207      * Public constants
208      */
209 
210     /**
211      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
212      * or a positive value, the animation restarts from the beginning.
213      */
214     public static final int RESTART = 1;
215     /**
216      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
217      * or a positive value, the animation reverses direction on every iteration.
218      */
219     public static final int REVERSE = 2;
220     /**
221      * This value used used with the {@link #setRepeatCount(int)} property to repeat
222      * the animation indefinitely.
223      */
224     public static final int INFINITE = -1;
225 
226 
227     /**
228      * @hide
229      */
setDurationScale(float durationScale)230     public static void setDurationScale(float durationScale) {
231         sDurationScale = durationScale;
232     }
233 
234     /**
235      * Creates a new ValueAnimator object. This default constructor is primarily for
236      * use internally; the factory methods which take parameters are more generally
237      * useful.
238      */
ValueAnimator()239     public ValueAnimator() {
240     }
241 
242     /**
243      * Constructs and returns a ValueAnimator that animates between int values. A single
244      * value implies that that value is the one being animated to. However, this is not typically
245      * useful in a ValueAnimator object because there is no way for the object to determine the
246      * starting value for the animation (unlike ObjectAnimator, which can derive that value
247      * from the target object and property being animated). Therefore, there should typically
248      * be two or more values.
249      *
250      * @param values A set of values that the animation will animate between over time.
251      * @return A ValueAnimator object that is set up to animate between the given values.
252      */
ofInt(int... values)253     public static ValueAnimator ofInt(int... values) {
254         ValueAnimator anim = new ValueAnimator();
255         anim.setIntValues(values);
256         return anim;
257     }
258 
259     /**
260      * Constructs and returns a ValueAnimator that animates between float values. A single
261      * value implies that that value is the one being animated to. However, this is not typically
262      * useful in a ValueAnimator object because there is no way for the object to determine the
263      * starting value for the animation (unlike ObjectAnimator, which can derive that value
264      * from the target object and property being animated). Therefore, there should typically
265      * be two or more values.
266      *
267      * @param values A set of values that the animation will animate between over time.
268      * @return A ValueAnimator object that is set up to animate between the given values.
269      */
ofFloat(float... values)270     public static ValueAnimator ofFloat(float... values) {
271         ValueAnimator anim = new ValueAnimator();
272         anim.setFloatValues(values);
273         return anim;
274     }
275 
276     /**
277      * Constructs and returns a ValueAnimator that animates between the values
278      * specified in the PropertyValuesHolder objects.
279      *
280      * @param values A set of PropertyValuesHolder objects whose values will be animated
281      * between over time.
282      * @return A ValueAnimator object that is set up to animate between the given values.
283      */
ofPropertyValuesHolder(PropertyValuesHolder... values)284     public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
285         ValueAnimator anim = new ValueAnimator();
286         anim.setValues(values);
287         return anim;
288     }
289     /**
290      * Constructs and returns a ValueAnimator that animates between Object values. A single
291      * value implies that that value is the one being animated to. However, this is not typically
292      * useful in a ValueAnimator object because there is no way for the object to determine the
293      * starting value for the animation (unlike ObjectAnimator, which can derive that value
294      * from the target object and property being animated). Therefore, there should typically
295      * be two or more values.
296      *
297      * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
298      * factory method also takes a TypeEvaluator object that the ValueAnimator will use
299      * to perform that interpolation.
300      *
301      * @param evaluator A TypeEvaluator that will be called on each animation frame to
302      * provide the ncessry interpolation between the Object values to derive the animated
303      * value.
304      * @param values A set of values that the animation will animate between over time.
305      * @return A ValueAnimator object that is set up to animate between the given values.
306      */
ofObject(TypeEvaluator evaluator, Object... values)307     public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
308         ValueAnimator anim = new ValueAnimator();
309         anim.setObjectValues(values);
310         anim.setEvaluator(evaluator);
311         return anim;
312     }
313 
314     /**
315      * Sets int values that will be animated between. A single
316      * value implies that that value is the one being animated to. However, this is not typically
317      * useful in a ValueAnimator object because there is no way for the object to determine the
318      * starting value for the animation (unlike ObjectAnimator, which can derive that value
319      * from the target object and property being animated). Therefore, there should typically
320      * be two or more values.
321      *
322      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
323      * than one PropertyValuesHolder object, this method will set the values for the first
324      * of those objects.</p>
325      *
326      * @param values A set of values that the animation will animate between over time.
327      */
setIntValues(int... values)328     public void setIntValues(int... values) {
329         if (values == null || values.length == 0) {
330             return;
331         }
332         if (mValues == null || mValues.length == 0) {
333             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)});
334         } else {
335             PropertyValuesHolder valuesHolder = mValues[0];
336             valuesHolder.setIntValues(values);
337         }
338         // New property/values/target should cause re-initialization prior to starting
339         mInitialized = false;
340     }
341 
342     /**
343      * Sets float values that will be animated between. A single
344      * value implies that that value is the one being animated to. However, this is not typically
345      * useful in a ValueAnimator object because there is no way for the object to determine the
346      * starting value for the animation (unlike ObjectAnimator, which can derive that value
347      * from the target object and property being animated). Therefore, there should typically
348      * be two or more values.
349      *
350      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
351      * than one PropertyValuesHolder object, this method will set the values for the first
352      * of those objects.</p>
353      *
354      * @param values A set of values that the animation will animate between over time.
355      */
setFloatValues(float... values)356     public void setFloatValues(float... values) {
357         if (values == null || values.length == 0) {
358             return;
359         }
360         if (mValues == null || mValues.length == 0) {
361             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)});
362         } else {
363             PropertyValuesHolder valuesHolder = mValues[0];
364             valuesHolder.setFloatValues(values);
365         }
366         // New property/values/target should cause re-initialization prior to starting
367         mInitialized = false;
368     }
369 
370     /**
371      * Sets the values to animate between for this animation. A single
372      * value implies that that value is the one being animated to. However, this is not typically
373      * useful in a ValueAnimator object because there is no way for the object to determine the
374      * starting value for the animation (unlike ObjectAnimator, which can derive that value
375      * from the target object and property being animated). Therefore, there should typically
376      * be two or more values.
377      *
378      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
379      * than one PropertyValuesHolder object, this method will set the values for the first
380      * of those objects.</p>
381      *
382      * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
383      * between these value objects. ValueAnimator only knows how to interpolate between the
384      * primitive types specified in the other setValues() methods.</p>
385      *
386      * @param values The set of values to animate between.
387      */
setObjectValues(Object... values)388     public void setObjectValues(Object... values) {
389         if (values == null || values.length == 0) {
390             return;
391         }
392         if (mValues == null || mValues.length == 0) {
393             setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("",
394                     (TypeEvaluator)null, values)});
395         } else {
396             PropertyValuesHolder valuesHolder = mValues[0];
397             valuesHolder.setObjectValues(values);
398         }
399         // New property/values/target should cause re-initialization prior to starting
400         mInitialized = false;
401     }
402 
403     /**
404      * Sets the values, per property, being animated between. This function is called internally
405      * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can
406      * be constructed without values and this method can be called to set the values manually
407      * instead.
408      *
409      * @param values The set of values, per property, being animated between.
410      */
setValues(PropertyValuesHolder... values)411     public void setValues(PropertyValuesHolder... values) {
412         int numValues = values.length;
413         mValues = values;
414         mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
415         for (int i = 0; i < numValues; ++i) {
416             PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
417             mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
418         }
419         // New property/values/target should cause re-initialization prior to starting
420         mInitialized = false;
421     }
422 
423     /**
424      * Returns the values that this ValueAnimator animates between. These values are stored in
425      * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
426      * of value objects instead.
427      *
428      * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
429      * values, per property, that define the animation.
430      */
getValues()431     public PropertyValuesHolder[] getValues() {
432         return mValues;
433     }
434 
435     /**
436      * This function is called immediately before processing the first animation
437      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
438      * function is called after that delay ends.
439      * It takes care of the final initialization steps for the
440      * animation.
441      *
442      *  <p>Overrides of this method should call the superclass method to ensure
443      *  that internal mechanisms for the animation are set up correctly.</p>
444      */
initAnimation()445     void initAnimation() {
446         if (!mInitialized) {
447             int numValues = mValues.length;
448             for (int i = 0; i < numValues; ++i) {
449                 mValues[i].init();
450             }
451             mInitialized = true;
452         }
453     }
454 
455 
456     /**
457      * Sets the length of the animation. The default duration is 300 milliseconds.
458      *
459      * @param duration The length of the animation, in milliseconds. This value cannot
460      * be negative.
461      * @return ValueAnimator The object called with setDuration(). This return
462      * value makes it easier to compose statements together that construct and then set the
463      * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
464      */
setDuration(long duration)465     public ValueAnimator setDuration(long duration) {
466         if (duration < 0) {
467             throw new IllegalArgumentException("Animators cannot have negative duration: " +
468                     duration);
469         }
470         mUnscaledDuration = duration;
471         mDuration = (long)(duration * sDurationScale);
472         return this;
473     }
474 
475     /**
476      * Gets the length of the animation. The default duration is 300 milliseconds.
477      *
478      * @return The length of the animation, in milliseconds.
479      */
getDuration()480     public long getDuration() {
481         return mUnscaledDuration;
482     }
483 
484     /**
485      * Sets the position of the animation to the specified point in time. This time should
486      * be between 0 and the total duration of the animation, including any repetition. If
487      * the animation has not yet been started, then it will not advance forward after it is
488      * set to this time; it will simply set the time to this value and perform any appropriate
489      * actions based on that time. If the animation is already running, then setCurrentPlayTime()
490      * will set the current playing time to this value and continue playing from that point.
491      *
492      * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
493      */
setCurrentPlayTime(long playTime)494     public void setCurrentPlayTime(long playTime) {
495         initAnimation();
496         long currentTime = AnimationUtils.currentAnimationTimeMillis();
497         if (mPlayingState != RUNNING) {
498             mSeekTime = playTime;
499             mPlayingState = SEEKED;
500         }
501         mStartTime = currentTime - playTime;
502         doAnimationFrame(currentTime);
503     }
504 
505     /**
506      * Gets the current position of the animation in time, which is equal to the current
507      * time minus the time that the animation started. An animation that is not yet started will
508      * return a value of zero.
509      *
510      * @return The current position in time of the animation.
511      */
getCurrentPlayTime()512     public long getCurrentPlayTime() {
513         if (!mInitialized || mPlayingState == STOPPED) {
514             return 0;
515         }
516         return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
517     }
518 
519     /**
520      * This custom, static handler handles the timing pulse that is shared by
521      * all active animations. This approach ensures that the setting of animation
522      * values will happen on the UI thread and that all animations will share
523      * the same times for calculating their values, which makes synchronizing
524      * animations possible.
525      *
526      * The handler uses the Choreographer for executing periodic callbacks.
527      */
528     private static class AnimationHandler implements Runnable {
529         // The per-thread list of all active animations
530         private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
531 
532         // The per-thread set of animations to be started on the next animation frame
533         private final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
534 
535         /**
536          * Internal per-thread collections used to avoid set collisions as animations start and end
537          * while being processed.
538          */
539         private final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
540         private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
541         private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
542 
543         private final Choreographer mChoreographer;
544         private boolean mAnimationScheduled;
545 
AnimationHandler()546         private AnimationHandler() {
547             mChoreographer = Choreographer.getInstance();
548         }
549 
550         /**
551          * Start animating on the next frame.
552          */
start()553         public void start() {
554             scheduleAnimation();
555         }
556 
doAnimationFrame(long frameTime)557         private void doAnimationFrame(long frameTime) {
558             // mPendingAnimations holds any animations that have requested to be started
559             // We're going to clear mPendingAnimations, but starting animation may
560             // cause more to be added to the pending list (for example, if one animation
561             // starting triggers another starting). So we loop until mPendingAnimations
562             // is empty.
563             while (mPendingAnimations.size() > 0) {
564                 ArrayList<ValueAnimator> pendingCopy =
565                         (ArrayList<ValueAnimator>) mPendingAnimations.clone();
566                 mPendingAnimations.clear();
567                 int count = pendingCopy.size();
568                 for (int i = 0; i < count; ++i) {
569                     ValueAnimator anim = pendingCopy.get(i);
570                     // If the animation has a startDelay, place it on the delayed list
571                     if (anim.mStartDelay == 0) {
572                         anim.startAnimation(this);
573                     } else {
574                         mDelayedAnims.add(anim);
575                     }
576                 }
577             }
578             // Next, process animations currently sitting on the delayed queue, adding
579             // them to the active animations if they are ready
580             int numDelayedAnims = mDelayedAnims.size();
581             for (int i = 0; i < numDelayedAnims; ++i) {
582                 ValueAnimator anim = mDelayedAnims.get(i);
583                 if (anim.delayedAnimationFrame(frameTime)) {
584                     mReadyAnims.add(anim);
585                 }
586             }
587             int numReadyAnims = mReadyAnims.size();
588             if (numReadyAnims > 0) {
589                 for (int i = 0; i < numReadyAnims; ++i) {
590                     ValueAnimator anim = mReadyAnims.get(i);
591                     anim.startAnimation(this);
592                     anim.mRunning = true;
593                     mDelayedAnims.remove(anim);
594                 }
595                 mReadyAnims.clear();
596             }
597 
598             // Now process all active animations. The return value from animationFrame()
599             // tells the handler whether it should now be ended
600             int numAnims = mAnimations.size();
601             int i = 0;
602             while (i < numAnims) {
603                 ValueAnimator anim = mAnimations.get(i);
604                 if (anim.doAnimationFrame(frameTime)) {
605                     mEndingAnims.add(anim);
606                 }
607                 if (mAnimations.size() == numAnims) {
608                     ++i;
609                 } else {
610                     // An animation might be canceled or ended by client code
611                     // during the animation frame. Check to see if this happened by
612                     // seeing whether the current index is the same as it was before
613                     // calling animationFrame(). Another approach would be to copy
614                     // animations to a temporary list and process that list instead,
615                     // but that entails garbage and processing overhead that would
616                     // be nice to avoid.
617                     --numAnims;
618                     mEndingAnims.remove(anim);
619                 }
620             }
621             if (mEndingAnims.size() > 0) {
622                 for (i = 0; i < mEndingAnims.size(); ++i) {
623                     mEndingAnims.get(i).endAnimation(this);
624                 }
625                 mEndingAnims.clear();
626             }
627 
628             // If there are still active or delayed animations, schedule a future call to
629             // onAnimate to process the next frame of the animations.
630             if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
631                 scheduleAnimation();
632             }
633         }
634 
635         // Called by the Choreographer.
636         @Override
run()637         public void run() {
638             mAnimationScheduled = false;
639             doAnimationFrame(mChoreographer.getFrameTime());
640         }
641 
scheduleAnimation()642         private void scheduleAnimation() {
643             if (!mAnimationScheduled) {
644                 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
645                 mAnimationScheduled = true;
646             }
647         }
648     }
649 
650     /**
651      * The amount of time, in milliseconds, to delay starting the animation after
652      * {@link #start()} is called.
653      *
654      * @return the number of milliseconds to delay running the animation
655      */
getStartDelay()656     public long getStartDelay() {
657         return mUnscaledStartDelay;
658     }
659 
660     /**
661      * The amount of time, in milliseconds, to delay starting the animation after
662      * {@link #start()} is called.
663 
664      * @param startDelay The amount of the delay, in milliseconds
665      */
setStartDelay(long startDelay)666     public void setStartDelay(long startDelay) {
667         this.mStartDelay = (long)(startDelay * sDurationScale);
668         mUnscaledStartDelay = startDelay;
669     }
670 
671     /**
672      * The amount of time, in milliseconds, between each frame of the animation. This is a
673      * requested time that the animation will attempt to honor, but the actual delay between
674      * frames may be different, depending on system load and capabilities. This is a static
675      * function because the same delay will be applied to all animations, since they are all
676      * run off of a single timing loop.
677      *
678      * The frame delay may be ignored when the animation system uses an external timing
679      * source, such as the display refresh rate (vsync), to govern animations.
680      *
681      * @return the requested time between frames, in milliseconds
682      */
getFrameDelay()683     public static long getFrameDelay() {
684         return Choreographer.getFrameDelay();
685     }
686 
687     /**
688      * The amount of time, in milliseconds, between each frame of the animation. This is a
689      * requested time that the animation will attempt to honor, but the actual delay between
690      * frames may be different, depending on system load and capabilities. This is a static
691      * function because the same delay will be applied to all animations, since they are all
692      * run off of a single timing loop.
693      *
694      * The frame delay may be ignored when the animation system uses an external timing
695      * source, such as the display refresh rate (vsync), to govern animations.
696      *
697      * @param frameDelay the requested time between frames, in milliseconds
698      */
setFrameDelay(long frameDelay)699     public static void setFrameDelay(long frameDelay) {
700         Choreographer.setFrameDelay(frameDelay);
701     }
702 
703     /**
704      * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
705      * property being animated. This value is only sensible while the animation is running. The main
706      * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
707      * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
708      * is called during each animation frame, immediately after the value is calculated.
709      *
710      * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
711      * the single property being animated. If there are several properties being animated
712      * (specified by several PropertyValuesHolder objects in the constructor), this function
713      * returns the animated value for the first of those objects.
714      */
getAnimatedValue()715     public Object getAnimatedValue() {
716         if (mValues != null && mValues.length > 0) {
717             return mValues[0].getAnimatedValue();
718         }
719         // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
720         return null;
721     }
722 
723     /**
724      * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
725      * The main purpose for this read-only property is to retrieve the value from the
726      * <code>ValueAnimator</code> during a call to
727      * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
728      * is called during each animation frame, immediately after the value is calculated.
729      *
730      * @return animatedValue The value most recently calculated for the named property
731      * by this <code>ValueAnimator</code>.
732      */
getAnimatedValue(String propertyName)733     public Object getAnimatedValue(String propertyName) {
734         PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
735         if (valuesHolder != null) {
736             return valuesHolder.getAnimatedValue();
737         } else {
738             // At least avoid crashing if called with bogus propertyName
739             return null;
740         }
741     }
742 
743     /**
744      * Sets how many times the animation should be repeated. If the repeat
745      * count is 0, the animation is never repeated. If the repeat count is
746      * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
747      * into account. The repeat count is 0 by default.
748      *
749      * @param value the number of times the animation should be repeated
750      */
setRepeatCount(int value)751     public void setRepeatCount(int value) {
752         mRepeatCount = value;
753     }
754     /**
755      * Defines how many times the animation should repeat. The default value
756      * is 0.
757      *
758      * @return the number of times the animation should repeat, or {@link #INFINITE}
759      */
getRepeatCount()760     public int getRepeatCount() {
761         return mRepeatCount;
762     }
763 
764     /**
765      * Defines what this animation should do when it reaches the end. This
766      * setting is applied only when the repeat count is either greater than
767      * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
768      *
769      * @param value {@link #RESTART} or {@link #REVERSE}
770      */
setRepeatMode(int value)771     public void setRepeatMode(int value) {
772         mRepeatMode = value;
773     }
774 
775     /**
776      * Defines what this animation should do when it reaches the end.
777      *
778      * @return either one of {@link #REVERSE} or {@link #RESTART}
779      */
getRepeatMode()780     public int getRepeatMode() {
781         return mRepeatMode;
782     }
783 
784     /**
785      * Adds a listener to the set of listeners that are sent update events through the life of
786      * an animation. This method is called on all listeners for every frame of the animation,
787      * after the values for the animation have been calculated.
788      *
789      * @param listener the listener to be added to the current set of listeners for this animation.
790      */
addUpdateListener(AnimatorUpdateListener listener)791     public void addUpdateListener(AnimatorUpdateListener listener) {
792         if (mUpdateListeners == null) {
793             mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
794         }
795         mUpdateListeners.add(listener);
796     }
797 
798     /**
799      * Removes all listeners from the set listening to frame updates for this animation.
800      */
removeAllUpdateListeners()801     public void removeAllUpdateListeners() {
802         if (mUpdateListeners == null) {
803             return;
804         }
805         mUpdateListeners.clear();
806         mUpdateListeners = null;
807     }
808 
809     /**
810      * Removes a listener from the set listening to frame updates for this animation.
811      *
812      * @param listener the listener to be removed from the current set of update listeners
813      * for this animation.
814      */
removeUpdateListener(AnimatorUpdateListener listener)815     public void removeUpdateListener(AnimatorUpdateListener listener) {
816         if (mUpdateListeners == null) {
817             return;
818         }
819         mUpdateListeners.remove(listener);
820         if (mUpdateListeners.size() == 0) {
821             mUpdateListeners = null;
822         }
823     }
824 
825 
826     /**
827      * The time interpolator used in calculating the elapsed fraction of this animation. The
828      * interpolator determines whether the animation runs with linear or non-linear motion,
829      * such as acceleration and deceleration. The default value is
830      * {@link android.view.animation.AccelerateDecelerateInterpolator}
831      *
832      * @param value the interpolator to be used by this animation. A value of <code>null</code>
833      * will result in linear interpolation.
834      */
835     @Override
setInterpolator(TimeInterpolator value)836     public void setInterpolator(TimeInterpolator value) {
837         if (value != null) {
838             mInterpolator = value;
839         } else {
840             mInterpolator = new LinearInterpolator();
841         }
842     }
843 
844     /**
845      * Returns the timing interpolator that this ValueAnimator uses.
846      *
847      * @return The timing interpolator for this ValueAnimator.
848      */
getInterpolator()849     public TimeInterpolator getInterpolator() {
850         return mInterpolator;
851     }
852 
853     /**
854      * The type evaluator to be used when calculating the animated values of this animation.
855      * The system will automatically assign a float or int evaluator based on the type
856      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
857      * are not one of these primitive types, or if different evaluation is desired (such as is
858      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
859      * For example, when running an animation on color values, the {@link ArgbEvaluator}
860      * should be used to get correct RGB color interpolation.
861      *
862      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
863      * will be used for that set. If there are several sets of values being animated, which is
864      * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator
865      * is assigned just to the first PropertyValuesHolder object.</p>
866      *
867      * @param value the evaluator to be used this animation
868      */
setEvaluator(TypeEvaluator value)869     public void setEvaluator(TypeEvaluator value) {
870         if (value != null && mValues != null && mValues.length > 0) {
871             mValues[0].setEvaluator(value);
872         }
873     }
874 
notifyStartListeners()875     private void notifyStartListeners() {
876         if (mListeners != null && !mStartListenersCalled) {
877             ArrayList<AnimatorListener> tmpListeners =
878                     (ArrayList<AnimatorListener>) mListeners.clone();
879             int numListeners = tmpListeners.size();
880             for (int i = 0; i < numListeners; ++i) {
881                 tmpListeners.get(i).onAnimationStart(this);
882             }
883         }
884         mStartListenersCalled = true;
885     }
886 
887     /**
888      * Start the animation playing. This version of start() takes a boolean flag that indicates
889      * whether the animation should play in reverse. The flag is usually false, but may be set
890      * to true if called from the reverse() method.
891      *
892      * <p>The animation started by calling this method will be run on the thread that called
893      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
894      * this is not the case). Also, if the animation will animate
895      * properties of objects in the view hierarchy, then the calling thread should be the UI
896      * thread for that view hierarchy.</p>
897      *
898      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
899      */
start(boolean playBackwards)900     private void start(boolean playBackwards) {
901         if (Looper.myLooper() == null) {
902             throw new AndroidRuntimeException("Animators may only be run on Looper threads");
903         }
904         mPlayingBackwards = playBackwards;
905         mCurrentIteration = 0;
906         mPlayingState = STOPPED;
907         mStarted = true;
908         mStartedDelay = false;
909         AnimationHandler animationHandler = getOrCreateAnimationHandler();
910         animationHandler.mPendingAnimations.add(this);
911         if (mStartDelay == 0) {
912             // This sets the initial value of the animation, prior to actually starting it running
913             setCurrentPlayTime(0);
914             mPlayingState = STOPPED;
915             mRunning = true;
916             notifyStartListeners();
917         }
918         animationHandler.start();
919     }
920 
921     @Override
start()922     public void start() {
923         start(false);
924     }
925 
926     @Override
cancel()927     public void cancel() {
928         // Only cancel if the animation is actually running or has been started and is about
929         // to run
930         AnimationHandler handler = getOrCreateAnimationHandler();
931         if (mPlayingState != STOPPED
932                 || handler.mPendingAnimations.contains(this)
933                 || handler.mDelayedAnims.contains(this)) {
934             // Only notify listeners if the animator has actually started
935             if ((mStarted || mRunning) && mListeners != null) {
936                 if (!mRunning) {
937                     // If it's not yet running, then start listeners weren't called. Call them now.
938                     notifyStartListeners();
939                 }
940                 ArrayList<AnimatorListener> tmpListeners =
941                         (ArrayList<AnimatorListener>) mListeners.clone();
942                 for (AnimatorListener listener : tmpListeners) {
943                     listener.onAnimationCancel(this);
944                 }
945             }
946             endAnimation(handler);
947         }
948     }
949 
950     @Override
end()951     public void end() {
952         AnimationHandler handler = getOrCreateAnimationHandler();
953         if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
954             // Special case if the animation has not yet started; get it ready for ending
955             mStartedDelay = false;
956             startAnimation(handler);
957             mStarted = true;
958         } else if (!mInitialized) {
959             initAnimation();
960         }
961         // The final value set on the target varies, depending on whether the animation
962         // was supposed to repeat an odd number of times
963         if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
964             animateValue(0f);
965         } else {
966             animateValue(1f);
967         }
968         endAnimation(handler);
969     }
970 
971     @Override
isRunning()972     public boolean isRunning() {
973         return (mPlayingState == RUNNING || mRunning);
974     }
975 
976     @Override
isStarted()977     public boolean isStarted() {
978         return mStarted;
979     }
980 
981     /**
982      * Plays the ValueAnimator in reverse. If the animation is already running,
983      * it will stop itself and play backwards from the point reached when reverse was called.
984      * If the animation is not currently running, then it will start from the end and
985      * play backwards. This behavior is only set for the current animation; future playing
986      * of the animation will use the default behavior of playing forward.
987      */
reverse()988     public void reverse() {
989         mPlayingBackwards = !mPlayingBackwards;
990         if (mPlayingState == RUNNING) {
991             long currentTime = AnimationUtils.currentAnimationTimeMillis();
992             long currentPlayTime = currentTime - mStartTime;
993             long timeLeft = mDuration - currentPlayTime;
994             mStartTime = currentTime - timeLeft;
995         } else {
996             start(true);
997         }
998     }
999 
1000     /**
1001      * Called internally to end an animation by removing it from the animations list. Must be
1002      * called on the UI thread.
1003      */
endAnimation(AnimationHandler handler)1004     private void endAnimation(AnimationHandler handler) {
1005         handler.mAnimations.remove(this);
1006         handler.mPendingAnimations.remove(this);
1007         handler.mDelayedAnims.remove(this);
1008         mPlayingState = STOPPED;
1009         if ((mStarted || mRunning) && mListeners != null) {
1010             if (!mRunning) {
1011                 // If it's not yet running, then start listeners weren't called. Call them now.
1012                 notifyStartListeners();
1013              }
1014             ArrayList<AnimatorListener> tmpListeners =
1015                     (ArrayList<AnimatorListener>) mListeners.clone();
1016             int numListeners = tmpListeners.size();
1017             for (int i = 0; i < numListeners; ++i) {
1018                 tmpListeners.get(i).onAnimationEnd(this);
1019             }
1020         }
1021         mRunning = false;
1022         mStarted = false;
1023         mStartListenersCalled = false;
1024     }
1025 
1026     /**
1027      * Called internally to start an animation by adding it to the active animations list. Must be
1028      * called on the UI thread.
1029      */
startAnimation(AnimationHandler handler)1030     private void startAnimation(AnimationHandler handler) {
1031         initAnimation();
1032         handler.mAnimations.add(this);
1033         if (mStartDelay > 0 && mListeners != null) {
1034             // Listeners were already notified in start() if startDelay is 0; this is
1035             // just for delayed animations
1036             notifyStartListeners();
1037         }
1038     }
1039 
1040     /**
1041      * Internal function called to process an animation frame on an animation that is currently
1042      * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
1043      * should be woken up and put on the active animations queue.
1044      *
1045      * @param currentTime The current animation time, used to calculate whether the animation
1046      * has exceeded its <code>startDelay</code> and should be started.
1047      * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
1048      * should be added to the set of active animations.
1049      */
delayedAnimationFrame(long currentTime)1050     private boolean delayedAnimationFrame(long currentTime) {
1051         if (!mStartedDelay) {
1052             mStartedDelay = true;
1053             mDelayStartTime = currentTime;
1054         } else {
1055             long deltaTime = currentTime - mDelayStartTime;
1056             if (deltaTime > mStartDelay) {
1057                 // startDelay ended - start the anim and record the
1058                 // mStartTime appropriately
1059                 mStartTime = currentTime - (deltaTime - mStartDelay);
1060                 mPlayingState = RUNNING;
1061                 return true;
1062             }
1063         }
1064         return false;
1065     }
1066 
1067     /**
1068      * This internal function processes a single animation frame for a given animation. The
1069      * currentTime parameter is the timing pulse sent by the handler, used to calculate the
1070      * elapsed duration, and therefore
1071      * the elapsed fraction, of the animation. The return value indicates whether the animation
1072      * should be ended (which happens when the elapsed time of the animation exceeds the
1073      * animation's duration, including the repeatCount).
1074      *
1075      * @param currentTime The current time, as tracked by the static timing handler
1076      * @return true if the animation's duration, including any repetitions due to
1077      * <code>repeatCount</code> has been exceeded and the animation should be ended.
1078      */
animationFrame(long currentTime)1079     boolean animationFrame(long currentTime) {
1080         boolean done = false;
1081         switch (mPlayingState) {
1082         case RUNNING:
1083         case SEEKED:
1084             float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
1085             if (fraction >= 1f) {
1086                 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
1087                     // Time to repeat
1088                     if (mListeners != null) {
1089                         int numListeners = mListeners.size();
1090                         for (int i = 0; i < numListeners; ++i) {
1091                             mListeners.get(i).onAnimationRepeat(this);
1092                         }
1093                     }
1094                     if (mRepeatMode == REVERSE) {
1095                         mPlayingBackwards = mPlayingBackwards ? false : true;
1096                     }
1097                     mCurrentIteration += (int)fraction;
1098                     fraction = fraction % 1f;
1099                     mStartTime += mDuration;
1100                 } else {
1101                     done = true;
1102                     fraction = Math.min(fraction, 1.0f);
1103                 }
1104             }
1105             if (mPlayingBackwards) {
1106                 fraction = 1f - fraction;
1107             }
1108             animateValue(fraction);
1109             break;
1110         }
1111 
1112         return done;
1113     }
1114 
1115     /**
1116      * Processes a frame of the animation, adjusting the start time if needed.
1117      *
1118      * @param frameTime The frame time.
1119      * @return true if the animation has ended.
1120      */
doAnimationFrame(long frameTime)1121     final boolean doAnimationFrame(long frameTime) {
1122         if (mPlayingState == STOPPED) {
1123             mPlayingState = RUNNING;
1124             if (mSeekTime < 0) {
1125                 mStartTime = frameTime;
1126             } else {
1127                 mStartTime = frameTime - mSeekTime;
1128                 // Now that we're playing, reset the seek time
1129                 mSeekTime = -1;
1130             }
1131         }
1132         // The frame time might be before the start time during the first frame of
1133         // an animation.  The "current time" must always be on or after the start
1134         // time to avoid animating frames at negative time intervals.  In practice, this
1135         // is very rare and only happens when seeking backwards.
1136         final long currentTime = Math.max(frameTime, mStartTime);
1137         return animationFrame(currentTime);
1138     }
1139 
1140     /**
1141      * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
1142      * the most recent frame update on the animation.
1143      *
1144      * @return Elapsed/interpolated fraction of the animation.
1145      */
getAnimatedFraction()1146     public float getAnimatedFraction() {
1147         return mCurrentFraction;
1148     }
1149 
1150     /**
1151      * This method is called with the elapsed fraction of the animation during every
1152      * animation frame. This function turns the elapsed fraction into an interpolated fraction
1153      * and then into an animated value (from the evaluator. The function is called mostly during
1154      * animation updates, but it is also called when the <code>end()</code>
1155      * function is called, to set the final value on the property.
1156      *
1157      * <p>Overrides of this method must call the superclass to perform the calculation
1158      * of the animated value.</p>
1159      *
1160      * @param fraction The elapsed fraction of the animation.
1161      */
animateValue(float fraction)1162     void animateValue(float fraction) {
1163         fraction = mInterpolator.getInterpolation(fraction);
1164         mCurrentFraction = fraction;
1165         int numValues = mValues.length;
1166         for (int i = 0; i < numValues; ++i) {
1167             mValues[i].calculateValue(fraction);
1168         }
1169         if (mUpdateListeners != null) {
1170             int numListeners = mUpdateListeners.size();
1171             for (int i = 0; i < numListeners; ++i) {
1172                 mUpdateListeners.get(i).onAnimationUpdate(this);
1173             }
1174         }
1175     }
1176 
1177     @Override
clone()1178     public ValueAnimator clone() {
1179         final ValueAnimator anim = (ValueAnimator) super.clone();
1180         if (mUpdateListeners != null) {
1181             ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
1182             anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
1183             int numListeners = oldListeners.size();
1184             for (int i = 0; i < numListeners; ++i) {
1185                 anim.mUpdateListeners.add(oldListeners.get(i));
1186             }
1187         }
1188         anim.mSeekTime = -1;
1189         anim.mPlayingBackwards = false;
1190         anim.mCurrentIteration = 0;
1191         anim.mInitialized = false;
1192         anim.mPlayingState = STOPPED;
1193         anim.mStartedDelay = false;
1194         PropertyValuesHolder[] oldValues = mValues;
1195         if (oldValues != null) {
1196             int numValues = oldValues.length;
1197             anim.mValues = new PropertyValuesHolder[numValues];
1198             anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
1199             for (int i = 0; i < numValues; ++i) {
1200                 PropertyValuesHolder newValuesHolder = oldValues[i].clone();
1201                 anim.mValues[i] = newValuesHolder;
1202                 anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
1203             }
1204         }
1205         return anim;
1206     }
1207 
1208     /**
1209      * Implementors of this interface can add themselves as update listeners
1210      * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
1211      * frame, after the current frame's values have been calculated for that
1212      * <code>ValueAnimator</code>.
1213      */
1214     public static interface AnimatorUpdateListener {
1215         /**
1216          * <p>Notifies the occurrence of another frame of the animation.</p>
1217          *
1218          * @param animation The animation which was repeated.
1219          */
onAnimationUpdate(ValueAnimator animation)1220         void onAnimationUpdate(ValueAnimator animation);
1221 
1222     }
1223 
1224     /**
1225      * Return the number of animations currently running.
1226      *
1227      * Used by StrictMode internally to annotate violations.
1228      * May be called on arbitrary threads!
1229      *
1230      * @hide
1231      */
getCurrentAnimationsCount()1232     public static int getCurrentAnimationsCount() {
1233         AnimationHandler handler = sAnimationHandler.get();
1234         return handler != null ? handler.mAnimations.size() : 0;
1235     }
1236 
1237     /**
1238      * Clear all animations on this thread, without canceling or ending them.
1239      * This should be used with caution.
1240      *
1241      * @hide
1242      */
clearAllAnimations()1243     public static void clearAllAnimations() {
1244         AnimationHandler handler = sAnimationHandler.get();
1245         if (handler != null) {
1246             handler.mAnimations.clear();
1247             handler.mPendingAnimations.clear();
1248             handler.mDelayedAnims.clear();
1249         }
1250     }
1251 
getOrCreateAnimationHandler()1252     private AnimationHandler getOrCreateAnimationHandler() {
1253         AnimationHandler handler = sAnimationHandler.get();
1254         if (handler == null) {
1255             handler = new AnimationHandler();
1256             sAnimationHandler.set(handler);
1257         }
1258         return handler;
1259     }
1260 
1261     @Override
toString()1262     public String toString() {
1263         String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
1264         if (mValues != null) {
1265             for (int i = 0; i < mValues.length; ++i) {
1266                 returnVal += "\n    " + mValues[i].toString();
1267             }
1268         }
1269         return returnVal;
1270     }
1271 }
1272