PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/SaberMod/pa-android-frameworks-base
Java | 1508 lines | 703 code | 114 blank | 691 comment | 205 complexity | 22b879b2b767ae4ba79d15e82f5cbe01 MD5 | raw file

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

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

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