PageRenderTime 57ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/library/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java

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

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