PageRenderTime 29ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/core/java/android/animation/ValueAnimator.java

https://bitbucket.org/kejar31/android_frameworks_base
Java | 1263 lines | 576 code | 98 blank | 589 comment | 149 complexity | 189bd3249f40dc5e6751f70d597cbdf7 MD5 | raw file
Possible License(s): CC0-1.0, BSD-3-Clause, LGPL-2.1

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

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