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