PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://bitbucket.org/htchoi1995/frameworks_base
Java | 1278 lines | 577 code | 101 blank | 600 comment | 149 complexity | fe79c563c13010413144055284cddbc3 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC0-1.0

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

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