PageRenderTime 105ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/backports/animation/ValueAnimator.java

https://bitbucket.org/fredgrott/gwsholointegration
Java | 1269 lines | 582 code | 98 blank | 589 comment | 149 complexity | e8ea1bfa7ee9084a5b8a6c18397874dd MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception

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

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