PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/core/java/android/animation/ValueAnimator.java

https://bitbucket.org/seandroid/frameworks-base
Java | 1608 lines | 757 code | 122 blank | 729 comment | 211 complexity | 9ad379b7c8957213a32cd1e8a9980283 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC0-1.0, BitTorrent-1.0

Large files files are truncated, but you can click here to view the full file

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

Large files files are truncated, but you can click here to view the full file