PageRenderTime 49ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/src/com/nineoldandroids/animation/ValueAnimator.java

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

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