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

/src/backports/animation/ValueAnimator.java

https://bitbucket.org/fredgrott/gwslaf
Java | 1260 lines | 573 code | 98 blank | 589 comment | 149 complexity | 2b58c12284bef1444e75f9deaf6e7745 MD5 | raw file

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

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