PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/ABS/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java

https://bitbucket.org/akravets/yahoo-weather-example
Java | 1267 lines | 576 code | 98 blank | 593 comment | 149 complexity | 74b1980afb55079e5ef84f592a102124 MD5 | raw file

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

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

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