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