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