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