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