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