ValueAnimator.java revision c6ffab32415a58bbb010dcd115684f9dbc249710
172961230a5890071bcca436eb5630172ce84ec41Andreas Huber/*
272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Copyright (C) 2010 The Android Open Source Project
372961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
572961230a5890071bcca436eb5630172ce84ec41Andreas Huber * you may not use this file except in compliance with the License.
672961230a5890071bcca436eb5630172ce84ec41Andreas Huber * You may obtain a copy of the License at
772961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
872961230a5890071bcca436eb5630172ce84ec41Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
972961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
1072961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Unless required by applicable law or agreed to in writing, software
1172961230a5890071bcca436eb5630172ce84ec41Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1372961230a5890071bcca436eb5630172ce84ec41Andreas Huber * See the License for the specific language governing permissions and
1472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * limitations under the License.
1572961230a5890071bcca436eb5630172ce84ec41Andreas Huber */
1672961230a5890071bcca436eb5630172ce84ec41Andreas Huber
1772961230a5890071bcca436eb5630172ce84ec41Andreas Huberpackage android.animation;
1872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
1972961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.os.Handler;
2072961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.os.Looper;
2172961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.os.Message;
2272961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.os.SystemProperties;
2372961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.util.AndroidRuntimeException;
2472961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.view.Choreographer;
2572961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.view.animation.AccelerateDecelerateInterpolator;
2672961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.view.animation.AnimationUtils;
2772961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport android.view.animation.LinearInterpolator;
2872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
2972961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.util.ArrayList;
3072961230a5890071bcca436eb5630172ce84ec41Andreas Huberimport java.util.HashMap;
3172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
3272961230a5890071bcca436eb5630172ce84ec41Andreas Huber/**
3372961230a5890071bcca436eb5630172ce84ec41Andreas Huber * This class provides a simple timing engine for running animations
3472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * which calculate animated values and set them on target objects.
3572961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
3672961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <p>There is a single timing pulse that all animations use. It runs in a
3772961230a5890071bcca436eb5630172ce84ec41Andreas Huber * custom handler to ensure that property changes happen on the UI thread.</p>
3872961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
3972961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <p>By default, ValueAnimator uses non-linear time interpolation, via the
4072961230a5890071bcca436eb5630172ce84ec41Andreas Huber * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
4172961230a5890071bcca436eb5630172ce84ec41Andreas Huber * out of an animation. This behavior can be changed by calling
4272961230a5890071bcca436eb5630172ce84ec41Andreas Huber * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
4372961230a5890071bcca436eb5630172ce84ec41Andreas Huber *
4472961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <div class="special reference">
4572961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <h3>Developer Guides</h3>
4672961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <p>For more information about animating with {@code ValueAnimator}, read the
4772961230a5890071bcca436eb5630172ce84ec41Andreas Huber * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property
4872961230a5890071bcca436eb5630172ce84ec41Andreas Huber * Animation</a> developer guide.</p>
4972961230a5890071bcca436eb5630172ce84ec41Andreas Huber * </div>
5072961230a5890071bcca436eb5630172ce84ec41Andreas Huber */
5172961230a5890071bcca436eb5630172ce84ec41Andreas Huberpublic class ValueAnimator extends Animator {
5272961230a5890071bcca436eb5630172ce84ec41Andreas Huber
5372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
5472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Internal constants
5572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
5672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private static float sDurationScale = 1.0f;
5772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
5872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
5972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Messages sent to timing handler: START is sent when an animation first begins.
6072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
6172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    static final int ANIMATION_START = 0;
6272961230a5890071bcca436eb5630172ce84ec41Andreas Huber
6372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
6472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Values used with internal variable mPlayingState to indicate the current state of an
6572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * animation.
6672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
6772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    static final int STOPPED    = 0; // Not yet playing
6872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    static final int RUNNING    = 1; // Playing normally
6972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    static final int SEEKED     = 2; // Seeked to some time value
7072961230a5890071bcca436eb5630172ce84ec41Andreas Huber
7172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
7272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Internal variables
7372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * NOTE: This object implements the clone() method, making a deep copy of any referenced
7472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * objects. As other non-trivial fields are added to this class, make sure to add logic
7572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * to clone() to make deep copies of them.
7672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
7772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
7872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // The first time that the animation's animateFrame() method is called. This time is used to
7972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
8072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // to animateFrame()
8172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    long mStartTime;
8272961230a5890071bcca436eb5630172ce84ec41Andreas Huber
8372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
8472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
8572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * to a value.
8672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
8772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    long mSeekTime = -1;
8872961230a5890071bcca436eb5630172ce84ec41Andreas Huber
8972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // The static sAnimationHandler processes the internal timing loop on which all animations
9072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // are based
9172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private static ThreadLocal<AnimationHandler> sAnimationHandler =
9272961230a5890071bcca436eb5630172ce84ec41Andreas Huber            new ThreadLocal<AnimationHandler>();
9372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
9472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // The time interpolator to be used if none is set on the animation
9572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private static final TimeInterpolator sDefaultInterpolator =
9672961230a5890071bcca436eb5630172ce84ec41Andreas Huber            new AccelerateDecelerateInterpolator();
9772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
9872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
9972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Used to indicate whether the animation is currently playing in reverse. This causes the
10072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * elapsed fraction to be inverted to calculate the appropriate values.
10172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
10272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private boolean mPlayingBackwards = false;
10372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
10472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
10572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
10672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * repeatCount (if repeatCount!=INFINITE), the animation ends
10772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
10872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private int mCurrentIteration = 0;
10972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
11072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
11172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
11272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
11372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private float mCurrentFraction = 0f;
11472961230a5890071bcca436eb5630172ce84ec41Andreas Huber
11572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
11672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Tracks whether a startDelay'd animation has begun playing through the startDelay.
11772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
11872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private boolean mStartedDelay = false;
11972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
12072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
12172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Tracks the time at which the animation began playing through its startDelay. This is
12272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * different from the mStartTime variable, which is used to track when the animation became
12372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * active (which is when the startDelay expired and the animation was added to the active
12472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * animations list).
12572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
12672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private long mDelayStartTime;
12772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
12872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
12972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Flag that represents the current state of the animation. Used to figure out when to start
13072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * an animation (if state == STOPPED). Also used to end an animation that
13172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * has been cancel()'d or end()'d since the last animation frame. Possible values are
13272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * STOPPED, RUNNING, SEEKED.
13372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
13472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    int mPlayingState = STOPPED;
13572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
13672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
13772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Additional playing state to indicate whether an animator has been start()'d. There is
13872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * some lag between a call to start() and the first animation frame. We should still note
13972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * that the animation has been started, even if it's first animation frame has not yet
14072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * happened, and reflect that state in isRunning().
14172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Note that delayed animations are different: they are not started until their first
14272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * animation frame, which occurs after their delay elapses.
14372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
14472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private boolean mRunning = false;
14572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
14672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
14772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Additional playing state to indicate whether an animator has been start()'d, whether or
14872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * not there is a nonzero startDelay.
14972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
15072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private boolean mStarted = false;
15172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
15272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
15372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Flag that denotes whether the animation is set up and ready to go. Used to
15472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * set up animation that has not yet been started.
15572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
15672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    boolean mInitialized = false;
15772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
15872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    //
15972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // Backing variables
16072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    //
16172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
16272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // How long the animation should last in ms
16372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private long mDuration = (long)(300 * sDurationScale);
16472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private long mUnscaledDuration = 300;
16572961230a5890071bcca436eb5630172ce84ec41Andreas Huber
16672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // The amount of time in ms to delay starting the animation after start() is called
16772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private long mStartDelay = 0;
16872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private long mUnscaledStartDelay = 0;
16972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
17072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // The number of times the animation will repeat. The default is 0, which means the animation
17172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    // will play only once
17272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private int mRepeatCount = 0;
17372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
17472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
17572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
17672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * animation will start from the beginning on every new cycle. REVERSE means the animation
17772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * will reverse directions on each iteration.
17872961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
17972961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private int mRepeatMode = RESTART;
18072961230a5890071bcca436eb5630172ce84ec41Andreas Huber
18172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
18272961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * The time interpolator to be used. The elapsed fraction of the animation will be passed
18372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * through this interpolator to calculate the interpolated fraction, which is then used to
18472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * calculate the animated values.
18572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
18672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private TimeInterpolator mInterpolator = sDefaultInterpolator;
18772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
18872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
18972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * The set of listeners to be sent events through the life of an animation.
19072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
19172961230a5890071bcca436eb5630172ce84ec41Andreas Huber    private ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
19272961230a5890071bcca436eb5630172ce84ec41Andreas Huber
19372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
19472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * The property/value sets being animated.
19572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
19672961230a5890071bcca436eb5630172ce84ec41Andreas Huber    PropertyValuesHolder[] mValues;
19772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
19872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
19972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
20072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * by property name during calls to getAnimatedValue(String).
20172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
20272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    HashMap<String, PropertyValuesHolder> mValuesMap;
20372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
20472961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
20572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Public constants
20672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
20772961230a5890071bcca436eb5630172ce84ec41Andreas Huber
20872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
20972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
21072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * or a positive value, the animation restarts from the beginning.
21172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
21272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public static final int RESTART = 1;
21372961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
21472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * When the animation reaches the end and <code>repeatCount</code> is INFINITE
21572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * or a positive value, the animation reverses direction on every iteration.
21672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
21772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public static final int REVERSE = 2;
21872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
21972961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * This value used used with the {@link #setRepeatCount(int)} property to repeat
22072961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * the animation indefinitely.
22172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
22272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public static final int INFINITE = -1;
22372961230a5890071bcca436eb5630172ce84ec41Andreas Huber
22472961230a5890071bcca436eb5630172ce84ec41Andreas Huber
22572961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
22672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * @hide
22772961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
22872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public static void setDurationScale(float durationScale) {
22972961230a5890071bcca436eb5630172ce84ec41Andreas Huber        sDurationScale = durationScale;
23072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
23172961230a5890071bcca436eb5630172ce84ec41Andreas Huber
23272961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
23372961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Creates a new ValueAnimator object. This default constructor is primarily for
23472961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * use internally; the factory methods which take parameters are more generally
23572961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * useful.
23672961230a5890071bcca436eb5630172ce84ec41Andreas Huber     */
23772961230a5890071bcca436eb5630172ce84ec41Andreas Huber    public ValueAnimator() {
23872961230a5890071bcca436eb5630172ce84ec41Andreas Huber    }
23972961230a5890071bcca436eb5630172ce84ec41Andreas Huber
24072961230a5890071bcca436eb5630172ce84ec41Andreas Huber    /**
24172961230a5890071bcca436eb5630172ce84ec41Andreas Huber     * Constructs and returns a ValueAnimator that animates between int values. A single
242     * value implies that that value is the one being animated to. However, this is not typically
243     * useful in a ValueAnimator object because there is no way for the object to determine the
244     * starting value for the animation (unlike ObjectAnimator, which can derive that value
245     * from the target object and property being animated). Therefore, there should typically
246     * be two or more values.
247     *
248     * @param values A set of values that the animation will animate between over time.
249     * @return A ValueAnimator object that is set up to animate between the given values.
250     */
251    public static ValueAnimator ofInt(int... values) {
252        ValueAnimator anim = new ValueAnimator();
253        anim.setIntValues(values);
254        return anim;
255    }
256
257    /**
258     * Constructs and returns a ValueAnimator that animates between float values. A single
259     * value implies that that value is the one being animated to. However, this is not typically
260     * useful in a ValueAnimator object because there is no way for the object to determine the
261     * starting value for the animation (unlike ObjectAnimator, which can derive that value
262     * from the target object and property being animated). Therefore, there should typically
263     * be two or more values.
264     *
265     * @param values A set of values that the animation will animate between over time.
266     * @return A ValueAnimator object that is set up to animate between the given values.
267     */
268    public static ValueAnimator ofFloat(float... values) {
269        ValueAnimator anim = new ValueAnimator();
270        anim.setFloatValues(values);
271        return anim;
272    }
273
274    /**
275     * Constructs and returns a ValueAnimator that animates between the values
276     * specified in the PropertyValuesHolder objects.
277     *
278     * @param values A set of PropertyValuesHolder objects whose values will be animated
279     * between over time.
280     * @return A ValueAnimator object that is set up to animate between the given values.
281     */
282    public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
283        ValueAnimator anim = new ValueAnimator();
284        anim.setValues(values);
285        return anim;
286    }
287    /**
288     * Constructs and returns a ValueAnimator that animates between Object values. A single
289     * value implies that that value is the one being animated to. However, this is not typically
290     * useful in a ValueAnimator object because there is no way for the object to determine the
291     * starting value for the animation (unlike ObjectAnimator, which can derive that value
292     * from the target object and property being animated). Therefore, there should typically
293     * be two or more values.
294     *
295     * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
296     * factory method also takes a TypeEvaluator object that the ValueAnimator will use
297     * to perform that interpolation.
298     *
299     * @param evaluator A TypeEvaluator that will be called on each animation frame to
300     * provide the ncessry interpolation between the Object values to derive the animated
301     * value.
302     * @param values A set of values that the animation will animate between over time.
303     * @return A ValueAnimator object that is set up to animate between the given values.
304     */
305    public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
306        ValueAnimator anim = new ValueAnimator();
307        anim.setObjectValues(values);
308        anim.setEvaluator(evaluator);
309        return anim;
310    }
311
312    /**
313     * Sets int values that will be animated between. A single
314     * value implies that that value is the one being animated to. However, this is not typically
315     * useful in a ValueAnimator object because there is no way for the object to determine the
316     * starting value for the animation (unlike ObjectAnimator, which can derive that value
317     * from the target object and property being animated). Therefore, there should typically
318     * be two or more values.
319     *
320     * <p>If there are already multiple sets of values defined for this ValueAnimator via more
321     * than one PropertyValuesHolder object, this method will set the values for the first
322     * of those objects.</p>
323     *
324     * @param values A set of values that the animation will animate between over time.
325     */
326    public void setIntValues(int... values) {
327        if (values == null || values.length == 0) {
328            return;
329        }
330        if (mValues == null || mValues.length == 0) {
331            setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)});
332        } else {
333            PropertyValuesHolder valuesHolder = mValues[0];
334            valuesHolder.setIntValues(values);
335        }
336        // New property/values/target should cause re-initialization prior to starting
337        mInitialized = false;
338    }
339
340    /**
341     * Sets float values that will be animated between. A single
342     * value implies that that value is the one being animated to. However, this is not typically
343     * useful in a ValueAnimator object because there is no way for the object to determine the
344     * starting value for the animation (unlike ObjectAnimator, which can derive that value
345     * from the target object and property being animated). Therefore, there should typically
346     * be two or more values.
347     *
348     * <p>If there are already multiple sets of values defined for this ValueAnimator via more
349     * than one PropertyValuesHolder object, this method will set the values for the first
350     * of those objects.</p>
351     *
352     * @param values A set of values that the animation will animate between over time.
353     */
354    public void setFloatValues(float... values) {
355        if (values == null || values.length == 0) {
356            return;
357        }
358        if (mValues == null || mValues.length == 0) {
359            setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)});
360        } else {
361            PropertyValuesHolder valuesHolder = mValues[0];
362            valuesHolder.setFloatValues(values);
363        }
364        // New property/values/target should cause re-initialization prior to starting
365        mInitialized = false;
366    }
367
368    /**
369     * Sets the values to animate between for this animation. A single
370     * value implies that that value is the one being animated to. However, this is not typically
371     * useful in a ValueAnimator object because there is no way for the object to determine the
372     * starting value for the animation (unlike ObjectAnimator, which can derive that value
373     * from the target object and property being animated). Therefore, there should typically
374     * be two or more values.
375     *
376     * <p>If there are already multiple sets of values defined for this ValueAnimator via more
377     * than one PropertyValuesHolder object, this method will set the values for the first
378     * of those objects.</p>
379     *
380     * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
381     * between these value objects. ValueAnimator only knows how to interpolate between the
382     * primitive types specified in the other setValues() methods.</p>
383     *
384     * @param values The set of values to animate between.
385     */
386    public void setObjectValues(Object... values) {
387        if (values == null || values.length == 0) {
388            return;
389        }
390        if (mValues == null || mValues.length == 0) {
391            setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("",
392                    (TypeEvaluator)null, values)});
393        } else {
394            PropertyValuesHolder valuesHolder = mValues[0];
395            valuesHolder.setObjectValues(values);
396        }
397        // New property/values/target should cause re-initialization prior to starting
398        mInitialized = false;
399    }
400
401    /**
402     * Sets the values, per property, being animated between. This function is called internally
403     * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can
404     * be constructed without values and this method can be called to set the values manually
405     * instead.
406     *
407     * @param values The set of values, per property, being animated between.
408     */
409    public void setValues(PropertyValuesHolder... values) {
410        int numValues = values.length;
411        mValues = values;
412        mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
413        for (int i = 0; i < numValues; ++i) {
414            PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i];
415            mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
416        }
417        // New property/values/target should cause re-initialization prior to starting
418        mInitialized = false;
419    }
420
421    /**
422     * Returns the values that this ValueAnimator animates between. These values are stored in
423     * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
424     * of value objects instead.
425     *
426     * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
427     * values, per property, that define the animation.
428     */
429    public PropertyValuesHolder[] getValues() {
430        return mValues;
431    }
432
433    /**
434     * This function is called immediately before processing the first animation
435     * frame of an animation. If there is a nonzero <code>startDelay</code>, the
436     * function is called after that delay ends.
437     * It takes care of the final initialization steps for the
438     * animation.
439     *
440     *  <p>Overrides of this method should call the superclass method to ensure
441     *  that internal mechanisms for the animation are set up correctly.</p>
442     */
443    void initAnimation() {
444        if (!mInitialized) {
445            int numValues = mValues.length;
446            for (int i = 0; i < numValues; ++i) {
447                mValues[i].init();
448            }
449            mInitialized = true;
450        }
451    }
452
453
454    /**
455     * Sets the length of the animation. The default duration is 300 milliseconds.
456     *
457     * @param duration The length of the animation, in milliseconds. This value cannot
458     * be negative.
459     * @return ValueAnimator The object called with setDuration(). This return
460     * value makes it easier to compose statements together that construct and then set the
461     * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
462     */
463    public ValueAnimator setDuration(long duration) {
464        if (duration < 0) {
465            throw new IllegalArgumentException("Animators cannot have negative duration: " +
466                    duration);
467        }
468        mUnscaledDuration = duration;
469        mDuration = (long)(duration * sDurationScale);
470        return this;
471    }
472
473    /**
474     * Gets the length of the animation. The default duration is 300 milliseconds.
475     *
476     * @return The length of the animation, in milliseconds.
477     */
478    public long getDuration() {
479        return mUnscaledDuration;
480    }
481
482    /**
483     * Sets the position of the animation to the specified point in time. This time should
484     * be between 0 and the total duration of the animation, including any repetition. If
485     * the animation has not yet been started, then it will not advance forward after it is
486     * set to this time; it will simply set the time to this value and perform any appropriate
487     * actions based on that time. If the animation is already running, then setCurrentPlayTime()
488     * will set the current playing time to this value and continue playing from that point.
489     *
490     * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
491     */
492    public void setCurrentPlayTime(long playTime) {
493        initAnimation();
494        long currentTime = AnimationUtils.currentAnimationTimeMillis();
495        if (mPlayingState != RUNNING) {
496            mSeekTime = playTime;
497            mPlayingState = SEEKED;
498        }
499        mStartTime = currentTime - playTime;
500        animationFrame(currentTime);
501    }
502
503    /**
504     * Gets the current position of the animation in time, which is equal to the current
505     * time minus the time that the animation started. An animation that is not yet started will
506     * return a value of zero.
507     *
508     * @return The current position in time of the animation.
509     */
510    public long getCurrentPlayTime() {
511        if (!mInitialized || mPlayingState == STOPPED) {
512            return 0;
513        }
514        return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
515    }
516
517    /**
518     * This custom, static handler handles the timing pulse that is shared by
519     * all active animations. This approach ensures that the setting of animation
520     * values will happen on the UI thread and that all animations will share
521     * the same times for calculating their values, which makes synchronizing
522     * animations possible.
523     *
524     */
525    private static class AnimationHandler extends Handler implements Runnable {
526        // The per-thread list of all active animations
527        private final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
528
529        // The per-thread set of animations to be started on the next animation frame
530        private final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
531
532        /**
533         * Internal per-thread collections used to avoid set collisions as animations start and end
534         * while being processed.
535         */
536        private final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
537        private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
538        private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
539
540        private final Choreographer mChoreographer;
541        private boolean mAnimationScheduled;
542
543        private AnimationHandler() {
544            mChoreographer = Choreographer.getInstance();
545        }
546
547        /**
548         * The START message is sent when an animation's start()  method is called.
549         * It cannot start synchronously when start() is called
550         * because the call may be on the wrong thread, and it would also not be
551         * synchronized with other animations because it would not start on a common
552         * timing pulse. So each animation sends a START message to the handler, which
553         * causes the handler to place the animation on the active animations queue and
554         * start processing frames for that animation.
555         */
556        @Override
557        public void handleMessage(Message msg) {
558            switch (msg.what) {
559                case ANIMATION_START:
560                    // If there are already active animations, or if another ANIMATION_START
561                    // message was processed during this frame, then the pending list may already
562                    // have been cleared. If that's the case, we've already processed the
563                    // active animations for this frame - don't do it again.
564                    if (mPendingAnimations.size() > 0) {
565                        doAnimationFrame();
566                    }
567                    break;
568            }
569        }
570
571        private void doAnimationFrame() {
572            // currentTime holds the common time for all animations processed
573            // during this frame
574            long currentTime = AnimationUtils.currentAnimationTimeMillis();
575
576            // mPendingAnimations holds any animations that have requested to be started
577            // We're going to clear mPendingAnimations, but starting animation may
578            // cause more to be added to the pending list (for example, if one animation
579            // starting triggers another starting). So we loop until mPendingAnimations
580            // is empty.
581            while (mPendingAnimations.size() > 0) {
582                ArrayList<ValueAnimator> pendingCopy =
583                        (ArrayList<ValueAnimator>) mPendingAnimations.clone();
584                mPendingAnimations.clear();
585                int count = pendingCopy.size();
586                for (int i = 0; i < count; ++i) {
587                    ValueAnimator anim = pendingCopy.get(i);
588                    // If the animation has a startDelay, place it on the delayed list
589                    if (anim.mStartDelay == 0) {
590                        anim.startAnimation(this);
591                    } else {
592                        mDelayedAnims.add(anim);
593                    }
594                }
595            }
596            // Next, process animations currently sitting on the delayed queue, adding
597            // them to the active animations if they are ready
598            int numDelayedAnims = mDelayedAnims.size();
599            for (int i = 0; i < numDelayedAnims; ++i) {
600                ValueAnimator anim = mDelayedAnims.get(i);
601                if (anim.delayedAnimationFrame(currentTime)) {
602                    mReadyAnims.add(anim);
603                }
604            }
605            int numReadyAnims = mReadyAnims.size();
606            if (numReadyAnims > 0) {
607                for (int i = 0; i < numReadyAnims; ++i) {
608                    ValueAnimator anim = mReadyAnims.get(i);
609                    anim.startAnimation(this);
610                    anim.mRunning = true;
611                    mDelayedAnims.remove(anim);
612                }
613                mReadyAnims.clear();
614            }
615
616            // Now process all active animations. The return value from animationFrame()
617            // tells the handler whether it should now be ended
618            int numAnims = mAnimations.size();
619            int i = 0;
620            while (i < numAnims) {
621                ValueAnimator anim = mAnimations.get(i);
622                if (anim.animationFrame(currentTime)) {
623                    mEndingAnims.add(anim);
624                }
625                if (mAnimations.size() == numAnims) {
626                    ++i;
627                } else {
628                    // An animation might be canceled or ended by client code
629                    // during the animation frame. Check to see if this happened by
630                    // seeing whether the current index is the same as it was before
631                    // calling animationFrame(). Another approach would be to copy
632                    // animations to a temporary list and process that list instead,
633                    // but that entails garbage and processing overhead that would
634                    // be nice to avoid.
635                    --numAnims;
636                    mEndingAnims.remove(anim);
637                }
638            }
639            if (mEndingAnims.size() > 0) {
640                for (i = 0; i < mEndingAnims.size(); ++i) {
641                    mEndingAnims.get(i).endAnimation(this);
642                }
643                mEndingAnims.clear();
644            }
645
646            // If there are still active or delayed animations, schedule a future call to
647            // onAnimate to process the next frame of the animations.
648            if (!mAnimationScheduled
649                    && (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty())) {
650                mChoreographer.postAnimationCallback(this, null);
651                mAnimationScheduled = true;
652            }
653        }
654
655        // Called by the Choreographer.
656        @Override
657        public void run() {
658            mAnimationScheduled = false;
659            doAnimationFrame();
660        }
661    }
662
663    /**
664     * The amount of time, in milliseconds, to delay starting the animation after
665     * {@link #start()} is called.
666     *
667     * @return the number of milliseconds to delay running the animation
668     */
669    public long getStartDelay() {
670        return mUnscaledStartDelay;
671    }
672
673    /**
674     * The amount of time, in milliseconds, to delay starting the animation after
675     * {@link #start()} is called.
676
677     * @param startDelay The amount of the delay, in milliseconds
678     */
679    public void setStartDelay(long startDelay) {
680        this.mStartDelay = (long)(startDelay * sDurationScale);
681        mUnscaledStartDelay = startDelay;
682    }
683
684    /**
685     * The amount of time, in milliseconds, between each frame of the animation. This is a
686     * requested time that the animation will attempt to honor, but the actual delay between
687     * frames may be different, depending on system load and capabilities. This is a static
688     * function because the same delay will be applied to all animations, since they are all
689     * run off of a single timing loop.
690     *
691     * The frame delay may be ignored when the animation system uses an external timing
692     * source, such as the display refresh rate (vsync), to govern animations.
693     *
694     * @return the requested time between frames, in milliseconds
695     */
696    public static long getFrameDelay() {
697        return Choreographer.getFrameDelay();
698    }
699
700    /**
701     * The amount of time, in milliseconds, between each frame of the animation. This is a
702     * requested time that the animation will attempt to honor, but the actual delay between
703     * frames may be different, depending on system load and capabilities. This is a static
704     * function because the same delay will be applied to all animations, since they are all
705     * run off of a single timing loop.
706     *
707     * The frame delay may be ignored when the animation system uses an external timing
708     * source, such as the display refresh rate (vsync), to govern animations.
709     *
710     * @param frameDelay the requested time between frames, in milliseconds
711     */
712    public static void setFrameDelay(long frameDelay) {
713        Choreographer.setFrameDelay(frameDelay);
714    }
715
716    /**
717     * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
718     * property being animated. This value is only sensible while the animation is running. The main
719     * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
720     * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
721     * is called during each animation frame, immediately after the value is calculated.
722     *
723     * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
724     * the single property being animated. If there are several properties being animated
725     * (specified by several PropertyValuesHolder objects in the constructor), this function
726     * returns the animated value for the first of those objects.
727     */
728    public Object getAnimatedValue() {
729        if (mValues != null && mValues.length > 0) {
730            return mValues[0].getAnimatedValue();
731        }
732        // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
733        return null;
734    }
735
736    /**
737     * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
738     * The main purpose for this read-only property is to retrieve the value from the
739     * <code>ValueAnimator</code> during a call to
740     * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
741     * is called during each animation frame, immediately after the value is calculated.
742     *
743     * @return animatedValue The value most recently calculated for the named property
744     * by this <code>ValueAnimator</code>.
745     */
746    public Object getAnimatedValue(String propertyName) {
747        PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
748        if (valuesHolder != null) {
749            return valuesHolder.getAnimatedValue();
750        } else {
751            // At least avoid crashing if called with bogus propertyName
752            return null;
753        }
754    }
755
756    /**
757     * Sets how many times the animation should be repeated. If the repeat
758     * count is 0, the animation is never repeated. If the repeat count is
759     * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
760     * into account. The repeat count is 0 by default.
761     *
762     * @param value the number of times the animation should be repeated
763     */
764    public void setRepeatCount(int value) {
765        mRepeatCount = value;
766    }
767    /**
768     * Defines how many times the animation should repeat. The default value
769     * is 0.
770     *
771     * @return the number of times the animation should repeat, or {@link #INFINITE}
772     */
773    public int getRepeatCount() {
774        return mRepeatCount;
775    }
776
777    /**
778     * Defines what this animation should do when it reaches the end. This
779     * setting is applied only when the repeat count is either greater than
780     * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
781     *
782     * @param value {@link #RESTART} or {@link #REVERSE}
783     */
784    public void setRepeatMode(int value) {
785        mRepeatMode = value;
786    }
787
788    /**
789     * Defines what this animation should do when it reaches the end.
790     *
791     * @return either one of {@link #REVERSE} or {@link #RESTART}
792     */
793    public int getRepeatMode() {
794        return mRepeatMode;
795    }
796
797    /**
798     * Adds a listener to the set of listeners that are sent update events through the life of
799     * an animation. This method is called on all listeners for every frame of the animation,
800     * after the values for the animation have been calculated.
801     *
802     * @param listener the listener to be added to the current set of listeners for this animation.
803     */
804    public void addUpdateListener(AnimatorUpdateListener listener) {
805        if (mUpdateListeners == null) {
806            mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
807        }
808        mUpdateListeners.add(listener);
809    }
810
811    /**
812     * Removes all listeners from the set listening to frame updates for this animation.
813     */
814    public void removeAllUpdateListeners() {
815        if (mUpdateListeners == null) {
816            return;
817        }
818        mUpdateListeners.clear();
819        mUpdateListeners = null;
820    }
821
822    /**
823     * Removes a listener from the set listening to frame updates for this animation.
824     *
825     * @param listener the listener to be removed from the current set of update listeners
826     * for this animation.
827     */
828    public void removeUpdateListener(AnimatorUpdateListener listener) {
829        if (mUpdateListeners == null) {
830            return;
831        }
832        mUpdateListeners.remove(listener);
833        if (mUpdateListeners.size() == 0) {
834            mUpdateListeners = null;
835        }
836    }
837
838
839    /**
840     * The time interpolator used in calculating the elapsed fraction of this animation. The
841     * interpolator determines whether the animation runs with linear or non-linear motion,
842     * such as acceleration and deceleration. The default value is
843     * {@link android.view.animation.AccelerateDecelerateInterpolator}
844     *
845     * @param value the interpolator to be used by this animation. A value of <code>null</code>
846     * will result in linear interpolation.
847     */
848    @Override
849    public void setInterpolator(TimeInterpolator value) {
850        if (value != null) {
851            mInterpolator = value;
852        } else {
853            mInterpolator = new LinearInterpolator();
854        }
855    }
856
857    /**
858     * Returns the timing interpolator that this ValueAnimator uses.
859     *
860     * @return The timing interpolator for this ValueAnimator.
861     */
862    public TimeInterpolator getInterpolator() {
863        return mInterpolator;
864    }
865
866    /**
867     * The type evaluator to be used when calculating the animated values of this animation.
868     * The system will automatically assign a float or int evaluator based on the type
869     * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
870     * are not one of these primitive types, or if different evaluation is desired (such as is
871     * necessary with int values that represent colors), a custom evaluator needs to be assigned.
872     * For example, when running an animation on color values, the {@link ArgbEvaluator}
873     * should be used to get correct RGB color interpolation.
874     *
875     * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
876     * will be used for that set. If there are several sets of values being animated, which is
877     * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator
878     * is assigned just to the first PropertyValuesHolder object.</p>
879     *
880     * @param value the evaluator to be used this animation
881     */
882    public void setEvaluator(TypeEvaluator value) {
883        if (value != null && mValues != null && mValues.length > 0) {
884            mValues[0].setEvaluator(value);
885        }
886    }
887
888    /**
889     * Start the animation playing. This version of start() takes a boolean flag that indicates
890     * whether the animation should play in reverse. The flag is usually false, but may be set
891     * to true if called from the reverse() method.
892     *
893     * <p>The animation started by calling this method will be run on the thread that called
894     * this method. This thread should have a Looper on it (a runtime exception will be thrown if
895     * this is not the case). Also, if the animation will animate
896     * properties of objects in the view hierarchy, then the calling thread should be the UI
897     * thread for that view hierarchy.</p>
898     *
899     * @param playBackwards Whether the ValueAnimator should start playing in reverse.
900     */
901    private void start(boolean playBackwards) {
902        if (Looper.myLooper() == null) {
903            throw new AndroidRuntimeException("Animators may only be run on Looper threads");
904        }
905        mPlayingBackwards = playBackwards;
906        mCurrentIteration = 0;
907        mPlayingState = STOPPED;
908        mStarted = true;
909        mStartedDelay = false;
910        AnimationHandler animationHandler = getOrCreateAnimationHandler();
911        animationHandler.mPendingAnimations.add(this);
912        if (mStartDelay == 0) {
913            // This sets the initial value of the animation, prior to actually starting it running
914            setCurrentPlayTime(getCurrentPlayTime());
915            mPlayingState = STOPPED;
916            mRunning = true;
917
918            if (mListeners != null) {
919                ArrayList<AnimatorListener> tmpListeners =
920                        (ArrayList<AnimatorListener>) mListeners.clone();
921                int numListeners = tmpListeners.size();
922                for (int i = 0; i < numListeners; ++i) {
923                    tmpListeners.get(i).onAnimationStart(this);
924                }
925            }
926        }
927        animationHandler.sendEmptyMessage(ANIMATION_START);
928    }
929
930    @Override
931    public void start() {
932        start(false);
933    }
934
935    @Override
936    public void cancel() {
937        // Only cancel if the animation is actually running or has been started and is about
938        // to run
939        AnimationHandler handler = getOrCreateAnimationHandler();
940        if (mPlayingState != STOPPED
941                || handler.mPendingAnimations.contains(this)
942                || handler.mDelayedAnims.contains(this)) {
943            // Only notify listeners if the animator has actually started
944            if (mRunning && mListeners != null) {
945                ArrayList<AnimatorListener> tmpListeners =
946                        (ArrayList<AnimatorListener>) mListeners.clone();
947                for (AnimatorListener listener : tmpListeners) {
948                    listener.onAnimationCancel(this);
949                }
950            }
951            endAnimation(handler);
952        }
953    }
954
955    @Override
956    public void end() {
957        AnimationHandler handler = getOrCreateAnimationHandler();
958        if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
959            // Special case if the animation has not yet started; get it ready for ending
960            mStartedDelay = false;
961            startAnimation(handler);
962        } else if (!mInitialized) {
963            initAnimation();
964        }
965        // The final value set on the target varies, depending on whether the animation
966        // was supposed to repeat an odd number of times
967        if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) {
968            animateValue(0f);
969        } else {
970            animateValue(1f);
971        }
972        endAnimation(handler);
973    }
974
975    @Override
976    public boolean isRunning() {
977        return (mPlayingState == RUNNING || mRunning);
978    }
979
980    @Override
981    public boolean isStarted() {
982        return mStarted;
983    }
984
985    /**
986     * Plays the ValueAnimator in reverse. If the animation is already running,
987     * it will stop itself and play backwards from the point reached when reverse was called.
988     * If the animation is not currently running, then it will start from the end and
989     * play backwards. This behavior is only set for the current animation; future playing
990     * of the animation will use the default behavior of playing forward.
991     */
992    public void reverse() {
993        mPlayingBackwards = !mPlayingBackwards;
994        if (mPlayingState == RUNNING) {
995            long currentTime = AnimationUtils.currentAnimationTimeMillis();
996            long currentPlayTime = currentTime - mStartTime;
997            long timeLeft = mDuration - currentPlayTime;
998            mStartTime = currentTime - timeLeft;
999        } else {
1000            start(true);
1001        }
1002    }
1003
1004    /**
1005     * Called internally to end an animation by removing it from the animations list. Must be
1006     * called on the UI thread.
1007     */
1008    private void endAnimation(AnimationHandler handler) {
1009        handler.mAnimations.remove(this);
1010        handler.mPendingAnimations.remove(this);
1011        handler.mDelayedAnims.remove(this);
1012        mPlayingState = STOPPED;
1013        if (mRunning && mListeners != null) {
1014            ArrayList<AnimatorListener> tmpListeners =
1015                    (ArrayList<AnimatorListener>) mListeners.clone();
1016            int numListeners = tmpListeners.size();
1017            for (int i = 0; i < numListeners; ++i) {
1018                tmpListeners.get(i).onAnimationEnd(this);
1019            }
1020        }
1021        mRunning = false;
1022        mStarted = false;
1023    }
1024
1025    /**
1026     * Called internally to start an animation by adding it to the active animations list. Must be
1027     * called on the UI thread.
1028     */
1029    private void startAnimation(AnimationHandler handler) {
1030        initAnimation();
1031        handler.mAnimations.add(this);
1032        if (mStartDelay > 0 && mListeners != null) {
1033            // Listeners were already notified in start() if startDelay is 0; this is
1034            // just for delayed animations
1035            ArrayList<AnimatorListener> tmpListeners =
1036                    (ArrayList<AnimatorListener>) mListeners.clone();
1037            int numListeners = tmpListeners.size();
1038            for (int i = 0; i < numListeners; ++i) {
1039                tmpListeners.get(i).onAnimationStart(this);
1040            }
1041        }
1042    }
1043
1044    /**
1045     * Internal function called to process an animation frame on an animation that is currently
1046     * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
1047     * should be woken up and put on the active animations queue.
1048     *
1049     * @param currentTime The current animation time, used to calculate whether the animation
1050     * has exceeded its <code>startDelay</code> and should be started.
1051     * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
1052     * should be added to the set of active animations.
1053     */
1054    private boolean delayedAnimationFrame(long currentTime) {
1055        if (!mStartedDelay) {
1056            mStartedDelay = true;
1057            mDelayStartTime = currentTime;
1058        } else {
1059            long deltaTime = currentTime - mDelayStartTime;
1060            if (deltaTime > mStartDelay) {
1061                // startDelay ended - start the anim and record the
1062                // mStartTime appropriately
1063                mStartTime = currentTime - (deltaTime - mStartDelay);
1064                mPlayingState = RUNNING;
1065                return true;
1066            }
1067        }
1068        return false;
1069    }
1070
1071    /**
1072     * This internal function processes a single animation frame for a given animation. The
1073     * currentTime parameter is the timing pulse sent by the handler, used to calculate the
1074     * elapsed duration, and therefore
1075     * the elapsed fraction, of the animation. The return value indicates whether the animation
1076     * should be ended (which happens when the elapsed time of the animation exceeds the
1077     * animation's duration, including the repeatCount).
1078     *
1079     * @param currentTime The current time, as tracked by the static timing handler
1080     * @return true if the animation's duration, including any repetitions due to
1081     * <code>repeatCount</code> has been exceeded and the animation should be ended.
1082     */
1083    boolean animationFrame(long currentTime) {
1084        boolean done = false;
1085
1086        if (mPlayingState == STOPPED) {
1087            mPlayingState = RUNNING;
1088            if (mSeekTime < 0) {
1089                mStartTime = currentTime;
1090            } else {
1091                mStartTime = currentTime - mSeekTime;
1092                // Now that we're playing, reset the seek time
1093                mSeekTime = -1;
1094            }
1095        }
1096        switch (mPlayingState) {
1097        case RUNNING:
1098        case SEEKED:
1099            float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
1100            if (fraction >= 1f) {
1101                if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
1102                    // Time to repeat
1103                    if (mListeners != null) {
1104                        int numListeners = mListeners.size();
1105                        for (int i = 0; i < numListeners; ++i) {
1106                            mListeners.get(i).onAnimationRepeat(this);
1107                        }
1108                    }
1109                    if (mRepeatMode == REVERSE) {
1110                        mPlayingBackwards = mPlayingBackwards ? false : true;
1111                    }
1112                    mCurrentIteration += (int)fraction;
1113                    fraction = fraction % 1f;
1114                    mStartTime += mDuration;
1115                } else {
1116                    done = true;
1117                    fraction = Math.min(fraction, 1.0f);
1118                }
1119            }
1120            if (mPlayingBackwards) {
1121                fraction = 1f - fraction;
1122            }
1123            animateValue(fraction);
1124            break;
1125        }
1126
1127        return done;
1128    }
1129
1130    /**
1131     * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
1132     * the most recent frame update on the animation.
1133     *
1134     * @return Elapsed/interpolated fraction of the animation.
1135     */
1136    public float getAnimatedFraction() {
1137        return mCurrentFraction;
1138    }
1139
1140    /**
1141     * This method is called with the elapsed fraction of the animation during every
1142     * animation frame. This function turns the elapsed fraction into an interpolated fraction
1143     * and then into an animated value (from the evaluator. The function is called mostly during
1144     * animation updates, but it is also called when the <code>end()</code>
1145     * function is called, to set the final value on the property.
1146     *
1147     * <p>Overrides of this method must call the superclass to perform the calculation
1148     * of the animated value.</p>
1149     *
1150     * @param fraction The elapsed fraction of the animation.
1151     */
1152    void animateValue(float fraction) {
1153        fraction = mInterpolator.getInterpolation(fraction);
1154        mCurrentFraction = fraction;
1155        int numValues = mValues.length;
1156        for (int i = 0; i < numValues; ++i) {
1157            mValues[i].calculateValue(fraction);
1158        }
1159        if (mUpdateListeners != null) {
1160            int numListeners = mUpdateListeners.size();
1161            for (int i = 0; i < numListeners; ++i) {
1162                mUpdateListeners.get(i).onAnimationUpdate(this);
1163            }
1164        }
1165    }
1166
1167    @Override
1168    public ValueAnimator clone() {
1169        final ValueAnimator anim = (ValueAnimator) super.clone();
1170        if (mUpdateListeners != null) {
1171            ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
1172            anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
1173            int numListeners = oldListeners.size();
1174            for (int i = 0; i < numListeners; ++i) {
1175                anim.mUpdateListeners.add(oldListeners.get(i));
1176            }
1177        }
1178        anim.mSeekTime = -1;
1179        anim.mPlayingBackwards = false;
1180        anim.mCurrentIteration = 0;
1181        anim.mInitialized = false;
1182        anim.mPlayingState = STOPPED;
1183        anim.mStartedDelay = false;
1184        PropertyValuesHolder[] oldValues = mValues;
1185        if (oldValues != null) {
1186            int numValues = oldValues.length;
1187            anim.mValues = new PropertyValuesHolder[numValues];
1188            anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
1189            for (int i = 0; i < numValues; ++i) {
1190                PropertyValuesHolder newValuesHolder = oldValues[i].clone();
1191                anim.mValues[i] = newValuesHolder;
1192                anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
1193            }
1194        }
1195        return anim;
1196    }
1197
1198    /**
1199     * Implementors of this interface can add themselves as update listeners
1200     * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
1201     * frame, after the current frame's values have been calculated for that
1202     * <code>ValueAnimator</code>.
1203     */
1204    public static interface AnimatorUpdateListener {
1205        /**
1206         * <p>Notifies the occurrence of another frame of the animation.</p>
1207         *
1208         * @param animation The animation which was repeated.
1209         */
1210        void onAnimationUpdate(ValueAnimator animation);
1211
1212    }
1213
1214    /**
1215     * Return the number of animations currently running.
1216     *
1217     * Used by StrictMode internally to annotate violations.
1218     * May be called on arbitrary threads!
1219     *
1220     * @hide
1221     */
1222    public static int getCurrentAnimationsCount() {
1223        AnimationHandler handler = sAnimationHandler.get();
1224        return handler != null ? handler.mAnimations.size() : 0;
1225    }
1226
1227    /**
1228     * Clear all animations on this thread, without canceling or ending them.
1229     * This should be used with caution.
1230     *
1231     * @hide
1232     */
1233    public static void clearAllAnimations() {
1234        AnimationHandler handler = sAnimationHandler.get();
1235        if (handler != null) {
1236            handler.mAnimations.clear();
1237            handler.mPendingAnimations.clear();
1238            handler.mDelayedAnims.clear();
1239        }
1240    }
1241
1242    private AnimationHandler getOrCreateAnimationHandler() {
1243        AnimationHandler handler = sAnimationHandler.get();
1244        if (handler == null) {
1245            handler = new AnimationHandler();
1246            sAnimationHandler.set(handler);
1247        }
1248        return handler;
1249    }
1250
1251    @Override
1252    public String toString() {
1253        String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
1254        if (mValues != null) {
1255            for (int i = 0; i < mValues.length; ++i) {
1256                returnVal += "\n    " + mValues[i].toString();
1257            }
1258        }
1259        return returnVal;
1260    }
1261}
1262