• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>Starting from API 23, it is also possible to use a combination of {@link PropertyValuesHolder}
53   * and {@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
setDurationScale(float durationScale)266      public static void setDurationScale(float durationScale) {
267          sDurationScale = durationScale;
268      }
269  
270      /**
271       * @hide
272       */
273      @TestApi
getDurationScale()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       */
ValueAnimator()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       */
ofInt(int... values)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       */
ofArgb(int... values)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       */
ofFloat(float... values)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       */
ofPropertyValuesHolder(PropertyValuesHolder... values)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       */
ofObject(TypeEvaluator evaluator, Object... values)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       */
setIntValues(int... values)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       */
setFloatValues(float... values)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       */
setObjectValues(Object... values)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       */
setValues(PropertyValuesHolder... values)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       */
getValues()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
initAnimation()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
setDuration(long duration)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  
getScaledDuration()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
getDuration()556      public long getDuration() {
557          return mDuration;
558      }
559  
560      @Override
getTotalDuration()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       */
setCurrentPlayTime(long playTime)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       */
setCurrentFraction(float fraction)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       */
getCurrentIteration(float fraction)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       */
getCurrentIterationFraction(float fraction)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       */
clampFraction(float fraction)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       */
shouldPlayBackward(int iteration)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       */
getCurrentPlayTime()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
getStartDelay()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
setStartDelay(long startDelay)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       */
getFrameDelay()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       */
setFrameDelay(long frameDelay)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       */
getAnimatedValue()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       */
getAnimatedValue(String propertyName)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       */
setRepeatCount(int value)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       */
getRepeatCount()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       */
setRepeatMode(@epeatMode int value)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
getRepeatMode()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       */
addUpdateListener(AnimatorUpdateListener listener)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       */
removeAllUpdateListeners()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       */
removeUpdateListener(AnimatorUpdateListener listener)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
setInterpolator(TimeInterpolator value)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
getInterpolator()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       */
setEvaluator(TypeEvaluator value)939      public void setEvaluator(TypeEvaluator value) {
940          if (value != null && mValues != null && mValues.length > 0) {
941              mValues[0].setEvaluator(value);
942          }
943      }
944  
notifyStartListeners()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       */
start(boolean playBackwards)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
start()1013      public void start() {
1014          start(false);
1015      }
1016  
1017      @Override
cancel()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
end()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
resume()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
pause()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
isRunning()1090      public boolean isRunning() {
1091          return mRunning;
1092      }
1093  
1094      @Override
isStarted()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
reverse()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
canReverse()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       */
endAnimation()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       */
startAnimation()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       */
isPulsingInternal()1195      private boolean isPulsingInternal() {
1196          return mLastFrameTime > 0;
1197      }
1198  
1199      /**
1200       * Returns the name of this animator for debugging purposes.
1201       */
getNameForTrace()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       */
commitAnimationFrame(long frameTime)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       */
animateBasedOnTime(long currentTime)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       */
doAnimationFrame(long frameTime)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       */
getAnimatedFraction()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
animateValue(float fraction)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
clone()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           */
onAnimationUpdate(ValueAnimator animation)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       */
getCurrentAnimationsCount()1415      public static int getCurrentAnimationsCount() {
1416          return AnimationHandler.getAnimationCount();
1417      }
1418  
1419      @Override
toString()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
setAllowRunningAsynchronously(boolean mayRunAsync)1465      public void setAllowRunningAsynchronously(boolean mayRunAsync) {
1466          // It is up to subclasses to support this, if they can.
1467      }
1468  }
1469