PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

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

https://github.com/android/platform_frameworks_base
Java | 1704 lines | 764 code | 133 blank | 807 comment | 208 complexity | 9e52807818f8d39be42e5575fe6015da MD5 | raw file
Possible License(s): Apache-2.0
  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.annotation.CallSuper;
  18. import android.annotation.IntDef;
  19. import android.annotation.Nullable;
  20. import android.annotation.TestApi;
  21. import android.compat.annotation.UnsupportedAppUsage;
  22. import android.os.Build;
  23. import android.os.Looper;
  24. import android.os.Trace;
  25. import android.util.AndroidRuntimeException;
  26. import android.util.Log;
  27. import android.view.animation.AccelerateDecelerateInterpolator;
  28. import android.view.animation.Animation;
  29. import android.view.animation.AnimationUtils;
  30. import android.view.animation.LinearInterpolator;
  31. import java.lang.annotation.Retention;
  32. import java.lang.annotation.RetentionPolicy;
  33. import java.util.ArrayList;
  34. import java.util.HashMap;
  35. /**
  36. * This class provides a simple timing engine for running animations
  37. * which calculate animated values and set them on target objects.
  38. *
  39. * <p>There is a single timing pulse that all animations use. It runs in a
  40. * custom handler to ensure that property changes happen on the UI thread.</p>
  41. *
  42. * <p>By default, ValueAnimator uses non-linear time interpolation, via the
  43. * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
  44. * out of an animation. This behavior can be changed by calling
  45. * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
  46. *
  47. * <p>Animators can be created from either code or resource files. Here is an example
  48. * of a ValueAnimator resource file:</p>
  49. *
  50. * {@sample development/samples/ApiDemos/res/anim/animator.xml ValueAnimatorResources}
  51. *
  52. * <p>Starting from API 23, it is also possible to use a combination of {@link PropertyValuesHolder}
  53. * and {@link Keyframe} resource tags to create a multi-step animation.
  54. * Note that you can specify explicit fractional values (from 0 to 1) for
  55. * each keyframe to determine when, in the overall duration, the animation should arrive at that
  56. * value. Alternatively, you can leave the fractions off and the keyframes will be equally
  57. * distributed within the total duration:</p>
  58. *
  59. * {@sample development/samples/ApiDemos/res/anim/value_animator_pvh_kf.xml
  60. * ValueAnimatorKeyframeResources}
  61. *
  62. * <div class="special reference">
  63. * <h3>Developer Guides</h3>
  64. * <p>For more information about animating with {@code ValueAnimator}, read the
  65. * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property
  66. * Animation</a> developer guide.</p>
  67. * </div>
  68. */
  69. @SuppressWarnings("unchecked")
  70. public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
  71. private static final String TAG = "ValueAnimator";
  72. private static final boolean DEBUG = false;
  73. /**
  74. * Internal constants
  75. */
  76. /**
  77. * System-wide animation scale.
  78. *
  79. * <p>To check whether animations are enabled system-wise use {@link #areAnimatorsEnabled()}.
  80. */
  81. @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
  82. private static float sDurationScale = 1.0f;
  83. /**
  84. * Internal variables
  85. * NOTE: This object implements the clone() method, making a deep copy of any referenced
  86. * objects. As other non-trivial fields are added to this class, make sure to add logic
  87. * to clone() to make deep copies of them.
  88. */
  89. /**
  90. * The first time that the animation's animateFrame() method is called. This time is used to
  91. * determine elapsed time (and therefore the elapsed fraction) in subsequent calls
  92. * to animateFrame().
  93. *
  94. * Whenever mStartTime is set, you must also update mStartTimeCommitted.
  95. */
  96. long mStartTime = -1;
  97. /**
  98. * When true, the start time has been firmly committed as a chosen reference point in
  99. * time by which the progress of the animation will be evaluated. When false, the
  100. * start time may be updated when the first animation frame is committed so as
  101. * to compensate for jank that may have occurred between when the start time was
  102. * initialized and when the frame was actually drawn.
  103. *
  104. * This flag is generally set to false during the first frame of the animation
  105. * when the animation playing state transitions from STOPPED to RUNNING or
  106. * resumes after having been paused. This flag is set to true when the start time
  107. * is firmly committed and should not be further compensated for jank.
  108. */
  109. boolean mStartTimeCommitted;
  110. /**
  111. * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
  112. * to a value.
  113. */
  114. float mSeekFraction = -1;
  115. /**
  116. * Set on the next frame after pause() is called, used to calculate a new startTime
  117. * or delayStartTime which allows the animator to continue from the point at which
  118. * it was paused. If negative, has not yet been set.
  119. */
  120. private long mPauseTime;
  121. /**
  122. * Set when an animator is resumed. This triggers logic in the next frame which
  123. * actually resumes the animator.
  124. */
  125. private boolean mResumed = false;
  126. // The time interpolator to be used if none is set on the animation
  127. private static final TimeInterpolator sDefaultInterpolator =
  128. new AccelerateDecelerateInterpolator();
  129. /**
  130. * Flag to indicate whether this animator is playing in reverse mode, specifically
  131. * by being started or interrupted by a call to reverse(). This flag is different than
  132. * mPlayingBackwards, which indicates merely whether the current iteration of the
  133. * animator is playing in reverse. It is used in corner cases to determine proper end
  134. * behavior.
  135. */
  136. private boolean mReversing;
  137. /**
  138. * Tracks the overall fraction of the animation, ranging from 0 to mRepeatCount + 1
  139. */
  140. private float mOverallFraction = 0f;
  141. /**
  142. * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
  143. * This is calculated by interpolating the fraction (range: [0, 1]) in the current iteration.
  144. */
  145. private float mCurrentFraction = 0f;
  146. /**
  147. * Tracks the time (in milliseconds) when the last frame arrived.
  148. */
  149. private long mLastFrameTime = -1;
  150. /**
  151. * Tracks the time (in milliseconds) when the first frame arrived. Note the frame may arrive
  152. * during the start delay.
  153. */
  154. private long mFirstFrameTime = -1;
  155. /**
  156. * Additional playing state to indicate whether an animator has been start()'d. There is
  157. * some lag between a call to start() and the first animation frame. We should still note
  158. * that the animation has been started, even if it's first animation frame has not yet
  159. * happened, and reflect that state in isRunning().
  160. * Note that delayed animations are different: they are not started until their first
  161. * animation frame, which occurs after their delay elapses.
  162. */
  163. private boolean mRunning = false;
  164. /**
  165. * Additional playing state to indicate whether an animator has been start()'d, whether or
  166. * not there is a nonzero startDelay.
  167. */
  168. private boolean mStarted = false;
  169. /**
  170. * Tracks whether we've notified listeners of the onAnimationStart() event. This can be
  171. * complex to keep track of since we notify listeners at different times depending on
  172. * startDelay and whether start() was called before end().
  173. */
  174. private boolean mStartListenersCalled = false;
  175. /**
  176. * Flag that denotes whether the animation is set up and ready to go. Used to
  177. * set up animation that has not yet been started.
  178. */
  179. boolean mInitialized = false;
  180. /**
  181. * Flag that tracks whether animation has been requested to end.
  182. */
  183. private boolean mAnimationEndRequested = false;
  184. //
  185. // Backing variables
  186. //
  187. // How long the animation should last in ms
  188. @UnsupportedAppUsage
  189. private long mDuration = 300;
  190. // The amount of time in ms to delay starting the animation after start() is called. Note
  191. // that this start delay is unscaled. When there is a duration scale set on the animator, the
  192. // scaling factor will be applied to this delay.
  193. private long mStartDelay = 0;
  194. // The number of times the animation will repeat. The default is 0, which means the animation
  195. // will play only once
  196. private int mRepeatCount = 0;
  197. /**
  198. * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
  199. * animation will start from the beginning on every new cycle. REVERSE means the animation
  200. * will reverse directions on each iteration.
  201. */
  202. private int mRepeatMode = RESTART;
  203. /**
  204. * Whether or not the animator should register for its own animation callback to receive
  205. * animation pulse.
  206. */
  207. private boolean mSelfPulse = true;
  208. /**
  209. * Whether or not the animator has been requested to start without pulsing. This flag gets set
  210. * in startWithoutPulsing(), and reset in start().
  211. */
  212. private boolean mSuppressSelfPulseRequested = false;
  213. /**
  214. * The time interpolator to be used. The elapsed fraction of the animation will be passed
  215. * through this interpolator to calculate the interpolated fraction, which is then used to
  216. * calculate the animated values.
  217. */
  218. private TimeInterpolator mInterpolator = sDefaultInterpolator;
  219. /**
  220. * The set of listeners to be sent events through the life of an animation.
  221. */
  222. ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
  223. /**
  224. * The property/value sets being animated.
  225. */
  226. PropertyValuesHolder[] mValues;
  227. /**
  228. * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
  229. * by property name during calls to getAnimatedValue(String).
  230. */
  231. HashMap<String, PropertyValuesHolder> mValuesMap;
  232. /**
  233. * If set to non-negative value, this will override {@link #sDurationScale}.
  234. */
  235. private float mDurationScale = -1f;
  236. /**
  237. * Animation handler used to schedule updates for this animation.
  238. */
  239. private AnimationHandler mAnimationHandler;
  240. /**
  241. * Public constants
  242. */
  243. /** @hide */
  244. @IntDef({RESTART, REVERSE})
  245. @Retention(RetentionPolicy.SOURCE)
  246. public @interface RepeatMode {}
  247. /**
  248. * When the animation reaches the end and <code>repeatCount</code> is INFINITE
  249. * or a positive value, the animation restarts from the beginning.
  250. */
  251. public static final int RESTART = 1;
  252. /**
  253. * When the animation reaches the end and <code>repeatCount</code> is INFINITE
  254. * or a positive value, the animation reverses direction on every iteration.
  255. */
  256. public static final int REVERSE = 2;
  257. /**
  258. * This value used used with the {@link #setRepeatCount(int)} property to repeat
  259. * the animation indefinitely.
  260. */
  261. public static final int INFINITE = -1;
  262. /**
  263. * @hide
  264. */
  265. @UnsupportedAppUsage
  266. @TestApi
  267. public static void setDurationScale(float durationScale) {
  268. sDurationScale = durationScale;
  269. }
  270. /**
  271. * @hide
  272. */
  273. @UnsupportedAppUsage
  274. @TestApi
  275. public static float getDurationScale() {
  276. return sDurationScale;
  277. }
  278. /**
  279. * Returns whether animators are currently enabled, system-wide. By default, all
  280. * animators are enabled. This can change if either the user sets a Developer Option
  281. * to set the animator duration scale to 0 or by Battery Savery mode being enabled
  282. * (which disables all animations).
  283. *
  284. * <p>Developers should not typically need to call this method, but should an app wish
  285. * to show a different experience when animators are disabled, this return value
  286. * can be used as a decider of which experience to offer.
  287. *
  288. * @return boolean Whether animators are currently enabled. The default value is
  289. * <code>true</code>.
  290. */
  291. public static boolean areAnimatorsEnabled() {
  292. return !(sDurationScale == 0);
  293. }
  294. /**
  295. * Creates a new ValueAnimator object. This default constructor is primarily for
  296. * use internally; the factory methods which take parameters are more generally
  297. * useful.
  298. */
  299. public ValueAnimator() {
  300. }
  301. /**
  302. * Constructs and returns a ValueAnimator that animates between int values. A single
  303. * value implies that that value is the one being animated to. However, this is not typically
  304. * useful in a ValueAnimator object because there is no way for the object to determine the
  305. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  306. * from the target object and property being animated). Therefore, there should typically
  307. * be two or more values.
  308. *
  309. * @param values A set of values that the animation will animate between over time.
  310. * @return A ValueAnimator object that is set up to animate between the given values.
  311. */
  312. public static ValueAnimator ofInt(int... values) {
  313. ValueAnimator anim = new ValueAnimator();
  314. anim.setIntValues(values);
  315. return anim;
  316. }
  317. /**
  318. * Constructs and returns a ValueAnimator that animates between color values. A single
  319. * value implies that that value is the one being animated to. However, this is not typically
  320. * useful in a ValueAnimator object because there is no way for the object to determine the
  321. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  322. * from the target object and property being animated). Therefore, there should typically
  323. * be two or more values.
  324. *
  325. * @param values A set of values that the animation will animate between over time.
  326. * @return A ValueAnimator object that is set up to animate between the given values.
  327. */
  328. public static ValueAnimator ofArgb(int... values) {
  329. ValueAnimator anim = new ValueAnimator();
  330. anim.setIntValues(values);
  331. anim.setEvaluator(ArgbEvaluator.getInstance());
  332. return anim;
  333. }
  334. /**
  335. * Constructs and returns a ValueAnimator that animates between float values. A single
  336. * value implies that that value is the one being animated to. However, this is not typically
  337. * useful in a ValueAnimator object because there is no way for the object to determine the
  338. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  339. * from the target object and property being animated). Therefore, there should typically
  340. * be two or more values.
  341. *
  342. * @param values A set of values that the animation will animate between over time.
  343. * @return A ValueAnimator object that is set up to animate between the given values.
  344. */
  345. public static ValueAnimator ofFloat(float... values) {
  346. ValueAnimator anim = new ValueAnimator();
  347. anim.setFloatValues(values);
  348. return anim;
  349. }
  350. /**
  351. * Constructs and returns a ValueAnimator that animates between the values
  352. * specified in the PropertyValuesHolder objects.
  353. *
  354. * @param values A set of PropertyValuesHolder objects whose values will be animated
  355. * between over time.
  356. * @return A ValueAnimator object that is set up to animate between the given values.
  357. */
  358. public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
  359. ValueAnimator anim = new ValueAnimator();
  360. anim.setValues(values);
  361. return anim;
  362. }
  363. /**
  364. * Constructs and returns a ValueAnimator that animates between Object values. A single
  365. * value implies that that value is the one being animated to. However, this is not typically
  366. * useful in a ValueAnimator object because there is no way for the object to determine the
  367. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  368. * from the target object and property being animated). Therefore, there should typically
  369. * be two or more values.
  370. *
  371. * <p><strong>Note:</strong> The Object values are stored as references to the original
  372. * objects, which means that changes to those objects after this method is called will
  373. * affect the values on the animator. If the objects will be mutated externally after
  374. * this method is called, callers should pass a copy of those objects instead.
  375. *
  376. * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
  377. * factory method also takes a TypeEvaluator object that the ValueAnimator will use
  378. * to perform that interpolation.
  379. *
  380. * @param evaluator A TypeEvaluator that will be called on each animation frame to
  381. * provide the ncessry interpolation between the Object values to derive the animated
  382. * value.
  383. * @param values A set of values that the animation will animate between over time.
  384. * @return A ValueAnimator object that is set up to animate between the given values.
  385. */
  386. public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
  387. ValueAnimator anim = new ValueAnimator();
  388. anim.setObjectValues(values);
  389. anim.setEvaluator(evaluator);
  390. return anim;
  391. }
  392. /**
  393. * Sets int values that will be animated between. A single
  394. * value implies that that value is the one being animated to. However, this is not typically
  395. * useful in a ValueAnimator object because there is no way for the object to determine the
  396. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  397. * from the target object and property being animated). Therefore, there should typically
  398. * be two or more values.
  399. *
  400. * <p>If there are already multiple sets of values defined for this ValueAnimator via more
  401. * than one PropertyValuesHolder object, this method will set the values for the first
  402. * of those objects.</p>
  403. *
  404. * @param values A set of values that the animation will animate between over time.
  405. */
  406. public void setIntValues(int... values) {
  407. if (values == null || values.length == 0) {
  408. return;
  409. }
  410. if (mValues == null || mValues.length == 0) {
  411. setValues(PropertyValuesHolder.ofInt("", values));
  412. } else {
  413. PropertyValuesHolder valuesHolder = mValues[0];
  414. valuesHolder.setIntValues(values);
  415. }
  416. // New property/values/target should cause re-initialization prior to starting
  417. mInitialized = false;
  418. }
  419. /**
  420. * Sets float values that will be animated between. A single
  421. * value implies that that value is the one being animated to. However, this is not typically
  422. * useful in a ValueAnimator object because there is no way for the object to determine the
  423. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  424. * from the target object and property being animated). Therefore, there should typically
  425. * be two or more values.
  426. *
  427. * <p>If there are already multiple sets of values defined for this ValueAnimator via more
  428. * than one PropertyValuesHolder object, this method will set the values for the first
  429. * of those objects.</p>
  430. *
  431. * @param values A set of values that the animation will animate between over time.
  432. */
  433. public void setFloatValues(float... values) {
  434. if (values == null || values.length == 0) {
  435. return;
  436. }
  437. if (mValues == null || mValues.length == 0) {
  438. setValues(PropertyValuesHolder.ofFloat("", values));
  439. } else {
  440. PropertyValuesHolder valuesHolder = mValues[0];
  441. valuesHolder.setFloatValues(values);
  442. }
  443. // New property/values/target should cause re-initialization prior to starting
  444. mInitialized = false;
  445. }
  446. /**
  447. * Sets the values to animate between for this animation. A single
  448. * value implies that that value is the one being animated to. However, this is not typically
  449. * useful in a ValueAnimator object because there is no way for the object to determine the
  450. * starting value for the animation (unlike ObjectAnimator, which can derive that value
  451. * from the target object and property being animated). Therefore, there should typically
  452. * be two or more values.
  453. *
  454. * <p><strong>Note:</strong> The Object values are stored as references to the original
  455. * objects, which means that changes to those objects after this method is called will
  456. * affect the values on the animator. If the objects will be mutated externally after
  457. * this method is called, callers should pass a copy of those objects instead.
  458. *
  459. * <p>If there are already multiple sets of values defined for this ValueAnimator via more
  460. * than one PropertyValuesHolder object, this method will set the values for the first
  461. * of those objects.</p>
  462. *
  463. * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
  464. * between these value objects. ValueAnimator only knows how to interpolate between the
  465. * primitive types specified in the other setValues() methods.</p>
  466. *
  467. * @param values The set of values to animate between.
  468. */
  469. public void setObjectValues(Object... values) {
  470. if (values == null || values.length == 0) {
  471. return;
  472. }
  473. if (mValues == null || mValues.length == 0) {
  474. setValues(PropertyValuesHolder.ofObject("", null, values));
  475. } else {
  476. PropertyValuesHolder valuesHolder = mValues[0];
  477. valuesHolder.setObjectValues(values);
  478. }
  479. // New property/values/target should cause re-initialization prior to starting
  480. mInitialized = false;
  481. }
  482. /**
  483. * Sets the values, per property, being animated between. This function is called internally
  484. * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can
  485. * be constructed without values and this method can be called to set the values manually
  486. * instead.
  487. *
  488. * @param values The set of values, per property, being animated between.
  489. */
  490. public void setValues(PropertyValuesHolder... values) {
  491. int numValues = values.length;
  492. mValues = values;
  493. mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
  494. for (int i = 0; i < numValues; ++i) {
  495. PropertyValuesHolder valuesHolder = values[i];
  496. mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
  497. }
  498. // New property/values/target should cause re-initialization prior to starting
  499. mInitialized = false;
  500. }
  501. /**
  502. * Returns the values that this ValueAnimator animates between. These values are stored in
  503. * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
  504. * of value objects instead.
  505. *
  506. * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
  507. * values, per property, that define the animation.
  508. */
  509. public PropertyValuesHolder[] getValues() {
  510. return mValues;
  511. }
  512. /**
  513. * This function is called immediately before processing the first animation
  514. * frame of an animation. If there is a nonzero <code>startDelay</code>, the
  515. * function is called after that delay ends.
  516. * It takes care of the final initialization steps for the
  517. * animation.
  518. *
  519. * <p>Overrides of this method should call the superclass method to ensure
  520. * that internal mechanisms for the animation are set up correctly.</p>
  521. */
  522. @CallSuper
  523. void initAnimation() {
  524. if (!mInitialized) {
  525. int numValues = mValues.length;
  526. for (int i = 0; i < numValues; ++i) {
  527. mValues[i].init();
  528. }
  529. mInitialized = true;
  530. }
  531. }
  532. /**
  533. * Sets the length of the animation. The default duration is 300 milliseconds.
  534. *
  535. * @param duration The length of the animation, in milliseconds. This value cannot
  536. * be negative.
  537. * @return ValueAnimator The object called with setDuration(). This return
  538. * value makes it easier to compose statements together that construct and then set the
  539. * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
  540. */
  541. @Override
  542. public ValueAnimator setDuration(long duration) {
  543. if (duration < 0) {
  544. throw new IllegalArgumentException("Animators cannot have negative duration: " +
  545. duration);
  546. }
  547. mDuration = duration;
  548. return this;
  549. }
  550. /**
  551. * Overrides the global duration scale by a custom value.
  552. *
  553. * @param durationScale The duration scale to set; or {@code -1f} to use the global duration
  554. * scale.
  555. * @hide
  556. */
  557. public void overrideDurationScale(float durationScale) {
  558. mDurationScale = durationScale;
  559. }
  560. private float resolveDurationScale() {
  561. return mDurationScale >= 0f ? mDurationScale : sDurationScale;
  562. }
  563. private long getScaledDuration() {
  564. return (long)(mDuration * resolveDurationScale());
  565. }
  566. /**
  567. * Gets the length of the animation. The default duration is 300 milliseconds.
  568. *
  569. * @return The length of the animation, in milliseconds.
  570. */
  571. @Override
  572. public long getDuration() {
  573. return mDuration;
  574. }
  575. @Override
  576. public long getTotalDuration() {
  577. if (mRepeatCount == INFINITE) {
  578. return DURATION_INFINITE;
  579. } else {
  580. return mStartDelay + (mDuration * (mRepeatCount + 1));
  581. }
  582. }
  583. /**
  584. * Sets the position of the animation to the specified point in time. This time should
  585. * be between 0 and the total duration of the animation, including any repetition. If
  586. * the animation has not yet been started, then it will not advance forward after it is
  587. * set to this time; it will simply set the time to this value and perform any appropriate
  588. * actions based on that time. If the animation is already running, then setCurrentPlayTime()
  589. * will set the current playing time to this value and continue playing from that point.
  590. *
  591. * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
  592. */
  593. public void setCurrentPlayTime(long playTime) {
  594. float fraction = mDuration > 0 ? (float) playTime / mDuration : 1;
  595. setCurrentFraction(fraction);
  596. }
  597. /**
  598. * Sets the position of the animation to the specified fraction. This fraction should
  599. * be between 0 and the total fraction of the animation, including any repetition. That is,
  600. * a fraction of 0 will position the animation at the beginning, a value of 1 at the end,
  601. * and a value of 2 at the end of a reversing animator that repeats once. If
  602. * the animation has not yet been started, then it will not advance forward after it is
  603. * set to this fraction; it will simply set the fraction to this value and perform any
  604. * appropriate actions based on that fraction. If the animation is already running, then
  605. * setCurrentFraction() will set the current fraction to this value and continue
  606. * playing from that point. {@link Animator.AnimatorListener} events are not called
  607. * due to changing the fraction; those events are only processed while the animation
  608. * is running.
  609. *
  610. * @param fraction The fraction to which the animation is advanced or rewound. Values
  611. * outside the range of 0 to the maximum fraction for the animator will be clamped to
  612. * the correct range.
  613. */
  614. public void setCurrentFraction(float fraction) {
  615. initAnimation();
  616. fraction = clampFraction(fraction);
  617. mStartTimeCommitted = true; // do not allow start time to be compensated for jank
  618. if (isPulsingInternal()) {
  619. long seekTime = (long) (getScaledDuration() * fraction);
  620. long currentTime = AnimationUtils.currentAnimationTimeMillis();
  621. // Only modify the start time when the animation is running. Seek fraction will ensure
  622. // non-running animations skip to the correct start time.
  623. mStartTime = currentTime - seekTime;
  624. } else {
  625. // If the animation loop hasn't started, or during start delay, the startTime will be
  626. // adjusted once the delay has passed based on seek fraction.
  627. mSeekFraction = fraction;
  628. }
  629. mOverallFraction = fraction;
  630. final float currentIterationFraction = getCurrentIterationFraction(fraction, mReversing);
  631. animateValue(currentIterationFraction);
  632. }
  633. /**
  634. * Calculates current iteration based on the overall fraction. The overall fraction will be
  635. * in the range of [0, mRepeatCount + 1]. Both current iteration and fraction in the current
  636. * iteration can be derived from it.
  637. */
  638. private int getCurrentIteration(float fraction) {
  639. fraction = clampFraction(fraction);
  640. // If the overall fraction is a positive integer, we consider the current iteration to be
  641. // complete. In other words, the fraction for the current iteration would be 1, and the
  642. // current iteration would be overall fraction - 1.
  643. double iteration = Math.floor(fraction);
  644. if (fraction == iteration && fraction > 0) {
  645. iteration--;
  646. }
  647. return (int) iteration;
  648. }
  649. /**
  650. * Calculates the fraction of the current iteration, taking into account whether the animation
  651. * should be played backwards. E.g. When the animation is played backwards in an iteration,
  652. * the fraction for that iteration will go from 1f to 0f.
  653. */
  654. private float getCurrentIterationFraction(float fraction, boolean inReverse) {
  655. fraction = clampFraction(fraction);
  656. int iteration = getCurrentIteration(fraction);
  657. float currentFraction = fraction - iteration;
  658. return shouldPlayBackward(iteration, inReverse) ? 1f - currentFraction : currentFraction;
  659. }
  660. /**
  661. * Clamps fraction into the correct range: [0, mRepeatCount + 1]. If repeat count is infinite,
  662. * no upper bound will be set for the fraction.
  663. *
  664. * @param fraction fraction to be clamped
  665. * @return fraction clamped into the range of [0, mRepeatCount + 1]
  666. */
  667. private float clampFraction(float fraction) {
  668. if (fraction < 0) {
  669. fraction = 0;
  670. } else if (mRepeatCount != INFINITE) {
  671. fraction = Math.min(fraction, mRepeatCount + 1);
  672. }
  673. return fraction;
  674. }
  675. /**
  676. * Calculates the direction of animation playing (i.e. forward or backward), based on 1)
  677. * whether the entire animation is being reversed, 2) repeat mode applied to the current
  678. * iteration.
  679. */
  680. private boolean shouldPlayBackward(int iteration, boolean inReverse) {
  681. if (iteration > 0 && mRepeatMode == REVERSE &&
  682. (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
  683. // if we were seeked to some other iteration in a reversing animator,
  684. // figure out the correct direction to start playing based on the iteration
  685. if (inReverse) {
  686. return (iteration % 2) == 0;
  687. } else {
  688. return (iteration % 2) != 0;
  689. }
  690. } else {
  691. return inReverse;
  692. }
  693. }
  694. /**
  695. * Gets the current position of the animation in time, which is equal to the current
  696. * time minus the time that the animation started. An animation that is not yet started will
  697. * return a value of zero, unless the animation has has its play time set via
  698. * {@link #setCurrentPlayTime(long)} or {@link #setCurrentFraction(float)}, in which case
  699. * it will return the time that was set.
  700. *
  701. * @return The current position in time of the animation.
  702. */
  703. public long getCurrentPlayTime() {
  704. if (!mInitialized || (!mStarted && mSeekFraction < 0)) {
  705. return 0;
  706. }
  707. if (mSeekFraction >= 0) {
  708. return (long) (mDuration * mSeekFraction);
  709. }
  710. float durationScale = resolveDurationScale();
  711. if (durationScale == 0f) {
  712. durationScale = 1f;
  713. }
  714. return (long) ((AnimationUtils.currentAnimationTimeMillis() - mStartTime) / durationScale);
  715. }
  716. /**
  717. * The amount of time, in milliseconds, to delay starting the animation after
  718. * {@link #start()} is called.
  719. *
  720. * @return the number of milliseconds to delay running the animation
  721. */
  722. @Override
  723. public long getStartDelay() {
  724. return mStartDelay;
  725. }
  726. /**
  727. * The amount of time, in milliseconds, to delay starting the animation after
  728. * {@link #start()} is called. Note that the start delay should always be non-negative. Any
  729. * negative start delay will be clamped to 0 on N and above.
  730. *
  731. * @param startDelay The amount of the delay, in milliseconds
  732. */
  733. @Override
  734. public void setStartDelay(long startDelay) {
  735. // Clamp start delay to non-negative range.
  736. if (startDelay < 0) {
  737. Log.w(TAG, "Start delay should always be non-negative");
  738. startDelay = 0;
  739. }
  740. mStartDelay = startDelay;
  741. }
  742. /**
  743. * The amount of time, in milliseconds, between each frame of the animation. This is a
  744. * requested time that the animation will attempt to honor, but the actual delay between
  745. * frames may be different, depending on system load and capabilities. This is a static
  746. * function because the same delay will be applied to all animations, since they are all
  747. * run off of a single timing loop.
  748. *
  749. * The frame delay may be ignored when the animation system uses an external timing
  750. * source, such as the display refresh rate (vsync), to govern animations.
  751. *
  752. * Note that this method should be called from the same thread that {@link #start()} is
  753. * called in order to check the frame delay for that animation. A runtime exception will be
  754. * thrown if the calling thread does not have a Looper.
  755. *
  756. * @return the requested time between frames, in milliseconds
  757. */
  758. public static long getFrameDelay() {
  759. return AnimationHandler.getInstance().getFrameDelay();
  760. }
  761. /**
  762. * The amount of time, in milliseconds, between each frame of the animation. This is a
  763. * requested time that the animation will attempt to honor, but the actual delay between
  764. * frames may be different, depending on system load and capabilities. This is a static
  765. * function because the same delay will be applied to all animations, since they are all
  766. * run off of a single timing loop.
  767. *
  768. * The frame delay may be ignored when the animation system uses an external timing
  769. * source, such as the display refresh rate (vsync), to govern animations.
  770. *
  771. * Note that this method should be called from the same thread that {@link #start()} is
  772. * called in order to have the new frame delay take effect on that animation. A runtime
  773. * exception will be thrown if the calling thread does not have a Looper.
  774. *
  775. * @param frameDelay the requested time between frames, in milliseconds
  776. */
  777. public static void setFrameDelay(long frameDelay) {
  778. AnimationHandler.getInstance().setFrameDelay(frameDelay);
  779. }
  780. /**
  781. * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
  782. * property being animated. This value is only sensible while the animation is running. The main
  783. * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
  784. * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
  785. * is called during each animation frame, immediately after the value is calculated.
  786. *
  787. * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
  788. * the single property being animated. If there are several properties being animated
  789. * (specified by several PropertyValuesHolder objects in the constructor), this function
  790. * returns the animated value for the first of those objects.
  791. */
  792. public Object getAnimatedValue() {
  793. if (mValues != null && mValues.length > 0) {
  794. return mValues[0].getAnimatedValue();
  795. }
  796. // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
  797. return null;
  798. }
  799. /**
  800. * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
  801. * The main purpose for this read-only property is to retrieve the value from the
  802. * <code>ValueAnimator</code> during a call to
  803. * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
  804. * is called during each animation frame, immediately after the value is calculated.
  805. *
  806. * @return animatedValue The value most recently calculated for the named property
  807. * by this <code>ValueAnimator</code>.
  808. */
  809. public Object getAnimatedValue(String propertyName) {
  810. PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
  811. if (valuesHolder != null) {
  812. return valuesHolder.getAnimatedValue();
  813. } else {
  814. // At least avoid crashing if called with bogus propertyName
  815. return null;
  816. }
  817. }
  818. /**
  819. * Sets how many times the animation should be repeated. If the repeat
  820. * count is 0, the animation is never repeated. If the repeat count is
  821. * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
  822. * into account. The repeat count is 0 by default.
  823. *
  824. * @param value the number of times the animation should be repeated
  825. */
  826. public void setRepeatCount(int value) {
  827. mRepeatCount = value;
  828. }
  829. /**
  830. * Defines how many times the animation should repeat. The default value
  831. * is 0.
  832. *
  833. * @return the number of times the animation should repeat, or {@link #INFINITE}
  834. */
  835. public int getRepeatCount() {
  836. return mRepeatCount;
  837. }
  838. /**
  839. * Defines what this animation should do when it reaches the end. This
  840. * setting is applied only when the repeat count is either greater than
  841. * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
  842. *
  843. * @param value {@link #RESTART} or {@link #REVERSE}
  844. */
  845. public void setRepeatMode(@RepeatMode int value) {
  846. mRepeatMode = value;
  847. }
  848. /**
  849. * Defines what this animation should do when it reaches the end.
  850. *
  851. * @return either one of {@link #REVERSE} or {@link #RESTART}
  852. */
  853. @RepeatMode
  854. public int getRepeatMode() {
  855. return mRepeatMode;
  856. }
  857. /**
  858. * Adds a listener to the set of listeners that are sent update events through the life of
  859. * an animation. This method is called on all listeners for every frame of the animation,
  860. * after the values for the animation have been calculated.
  861. *
  862. * @param listener the listener to be added to the current set of listeners for this animation.
  863. */
  864. public void addUpdateListener(AnimatorUpdateListener listener) {
  865. if (mUpdateListeners == null) {
  866. mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
  867. }
  868. mUpdateListeners.add(listener);
  869. }
  870. /**
  871. * Removes all listeners from the set listening to frame updates for this animation.
  872. */
  873. public void removeAllUpdateListeners() {
  874. if (mUpdateListeners == null) {
  875. return;
  876. }
  877. mUpdateListeners.clear();
  878. mUpdateListeners = null;
  879. }
  880. /**
  881. * Removes a listener from the set listening to frame updates for this animation.
  882. *
  883. * @param listener the listener to be removed from the current set of update listeners
  884. * for this animation.
  885. */
  886. public void removeUpdateListener(AnimatorUpdateListener listener) {
  887. if (mUpdateListeners == null) {
  888. return;
  889. }
  890. mUpdateListeners.remove(listener);
  891. if (mUpdateListeners.size() == 0) {
  892. mUpdateListeners = null;
  893. }
  894. }
  895. /**
  896. * The time interpolator used in calculating the elapsed fraction of this animation. The
  897. * interpolator determines whether the animation runs with linear or non-linear motion,
  898. * such as acceleration and deceleration. The default value is
  899. * {@link android.view.animation.AccelerateDecelerateInterpolator}
  900. *
  901. * @param value the interpolator to be used by this animation. A value of <code>null</code>
  902. * will result in linear interpolation.
  903. */
  904. @Override
  905. public void setInterpolator(TimeInterpolator value) {
  906. if (value != null) {
  907. mInterpolator = value;
  908. } else {
  909. mInterpolator = new LinearInterpolator();
  910. }
  911. }
  912. /**
  913. * Returns the timing interpolator that this ValueAnimator uses.
  914. *
  915. * @return The timing interpolator for this ValueAnimator.
  916. */
  917. @Override
  918. public TimeInterpolator getInterpolator() {
  919. return mInterpolator;
  920. }
  921. /**
  922. * The type evaluator to be used when calculating the animated values of this animation.
  923. * The system will automatically assign a float or int evaluator based on the type
  924. * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
  925. * are not one of these primitive types, or if different evaluation is desired (such as is
  926. * necessary with int values that represent colors), a custom evaluator needs to be assigned.
  927. * For example, when running an animation on color values, the {@link ArgbEvaluator}
  928. * should be used to get correct RGB color interpolation.
  929. *
  930. * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
  931. * will be used for that set. If there are several sets of values being animated, which is
  932. * the case if PropertyValuesHolder objects were set on the ValueAnimator, then the evaluator
  933. * is assigned just to the first PropertyValuesHolder object.</p>
  934. *
  935. * @param value the evaluator to be used this animation
  936. */
  937. public void setEvaluator(TypeEvaluator value) {
  938. if (value != null && mValues != null && mValues.length > 0) {
  939. mValues[0].setEvaluator(value);
  940. }
  941. }
  942. private void notifyStartListeners() {
  943. if (mListeners != null && !mStartListenersCalled) {
  944. ArrayList<AnimatorListener> tmpListeners =
  945. (ArrayList<AnimatorListener>) mListeners.clone();
  946. int numListeners = tmpListeners.size();
  947. for (int i = 0; i < numListeners; ++i) {
  948. tmpListeners.get(i).onAnimationStart(this, mReversing);
  949. }
  950. }
  951. mStartListenersCalled = true;
  952. }
  953. /**
  954. * Start the animation playing. This version of start() takes a boolean flag that indicates
  955. * whether the animation should play in reverse. The flag is usually false, but may be set
  956. * to true if called from the reverse() method.
  957. *
  958. * <p>The animation started by calling this method will be run on the thread that called
  959. * this method. This thread should have a Looper on it (a runtime exception will be thrown if
  960. * this is not the case). Also, if the animation will animate
  961. * properties of objects in the view hierarchy, then the calling thread should be the UI
  962. * thread for that view hierarchy.</p>
  963. *
  964. * @param playBackwards Whether the ValueAnimator should start playing in reverse.
  965. */
  966. private void start(boolean playBackwards) {
  967. if (Looper.myLooper() == null) {
  968. throw new AndroidRuntimeException("Animators may only be run on Looper threads");
  969. }
  970. mReversing = playBackwards;
  971. mSelfPulse = !mSuppressSelfPulseRequested;
  972. // Special case: reversing from seek-to-0 should act as if not seeked at all.
  973. if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) {
  974. if (mRepeatCount == INFINITE) {
  975. // Calculate the fraction of the current iteration.
  976. float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction));
  977. mSeekFraction = 1 - fraction;
  978. } else {
  979. mSeekFraction = 1 + mRepeatCount - mSeekFraction;
  980. }
  981. }
  982. mStarted = true;
  983. mPaused = false;
  984. mRunning = false;
  985. mAnimationEndRequested = false;
  986. // Resets mLastFrameTime when start() is called, so that if the animation was running,
  987. // calling start() would put the animation in the
  988. // started-but-not-yet-reached-the-first-frame phase.
  989. mLastFrameTime = -1;
  990. mFirstFrameTime = -1;
  991. mStartTime = -1;
  992. addAnimationCallback(0);
  993. if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) {
  994. // If there's no start delay, init the animation and notify start listeners right away
  995. // to be consistent with the previous behavior. Otherwise, postpone this until the first
  996. // frame after the start delay.
  997. startAnimation();
  998. if (mSeekFraction == -1) {
  999. // No seek, start at play time 0. Note that the reason we are not using fraction 0
  1000. // is because for animations with 0 duration, we want to be consistent with pre-N
  1001. // behavior: skip to the final value immediately.
  1002. setCurrentPlayTime(0);
  1003. } else {
  1004. setCurrentFraction(mSeekFraction);
  1005. }
  1006. }
  1007. }
  1008. void startWithoutPulsing(boolean inReverse) {
  1009. mSuppressSelfPulseRequested = true;
  1010. if (inReverse) {
  1011. reverse();
  1012. } else {
  1013. start();
  1014. }
  1015. mSuppressSelfPulseRequested = false;
  1016. }
  1017. @Override
  1018. public void start() {
  1019. start(false);
  1020. }
  1021. @Override
  1022. public void cancel() {
  1023. if (Looper.myLooper() == null) {
  1024. throw new AndroidRuntimeException("Animators may only be run on Looper threads");
  1025. }
  1026. // If end has already been requested, through a previous end() or cancel() call, no-op
  1027. // until animation starts again.
  1028. if (mAnimationEndRequested) {
  1029. return;
  1030. }
  1031. // Only cancel if the animation is actually running or has been started and is about
  1032. // to run
  1033. // Only notify listeners if the animator has actually started
  1034. if ((mStarted || mRunning) && mListeners != null) {
  1035. if (!mRunning) {
  1036. // If it's not yet running, then start listeners weren't called. Call them now.
  1037. notifyStartListeners();
  1038. }
  1039. ArrayList<AnimatorListener> tmpListeners =
  1040. (ArrayList<AnimatorListener>) mListeners.clone();
  1041. for (AnimatorListener listener : tmpListeners) {
  1042. listener.onAnimationCancel(this);
  1043. }
  1044. }
  1045. endAnimation();
  1046. }
  1047. @Override
  1048. public void end() {
  1049. if (Looper.myLooper() == null) {
  1050. throw new AndroidRuntimeException("Animators may only be run on Looper threads");
  1051. }
  1052. if (!mRunning) {
  1053. // Special case if the animation has not yet started; get it ready for ending
  1054. startAnimation();
  1055. mStarted = true;
  1056. } else if (!mInitialized) {
  1057. initAnimation();
  1058. }
  1059. animateValue(shouldPlayBackward(mRepeatCount, mReversing) ? 0f : 1f);
  1060. endAnimation();
  1061. }
  1062. @Override
  1063. public void resume() {
  1064. if (Looper.myLooper() == null) {
  1065. throw new AndroidRuntimeException("Animators may only be resumed from the same " +
  1066. "thread that the animator was started on");
  1067. }
  1068. if (mPaused && !mResumed) {
  1069. mResumed = true;
  1070. if (mPauseTime > 0) {
  1071. addAnimationCallback(0);
  1072. }
  1073. }
  1074. super.resume();
  1075. }
  1076. @Override
  1077. public void pause() {
  1078. boolean previouslyPaused = mPaused;
  1079. super.pause();
  1080. if (!previouslyPaused && mPaused) {
  1081. mPauseTime = -1;
  1082. mResumed = false;
  1083. }
  1084. }
  1085. @Override
  1086. public boolean isRunning() {
  1087. return mRunning;
  1088. }
  1089. @Override
  1090. public boolean isStarted() {
  1091. return mStarted;
  1092. }
  1093. /**
  1094. * Plays the ValueAnimator in reverse. If the animation is already running,
  1095. * it will stop itself and play backwards from the point reached when reverse was called.
  1096. * If the animation is not currently running, then it will start from the end and
  1097. * play backwards. This behavior is only set for the current animation; future playing
  1098. * of the animation will use the default behavior of playing forward.
  1099. */
  1100. @Override
  1101. public void reverse() {
  1102. if (isPulsingInternal()) {
  1103. long currentTime = AnimationUtils.currentAnimationTimeMillis();
  1104. long currentPlayTime = currentTime - mStartTime;
  1105. long timeLeft = getScaledDuration() - currentPlayTime;
  1106. mStartTime = currentTime - timeLeft;
  1107. mStartTimeCommitted = true; // do not allow start time to be compensated for jank
  1108. mReversing = !mReversing;
  1109. } else if (mStarted) {
  1110. mReversing = !mReversing;
  1111. end();
  1112. } else {
  1113. start(true);
  1114. }
  1115. }
  1116. /**
  1117. * @hide
  1118. */
  1119. @Override
  1120. public boolean canReverse() {
  1121. return true;
  1122. }
  1123. /**
  1124. * Called internally to end an animation by removing it from the animations list. Must be
  1125. * called on the UI thread.
  1126. */
  1127. private void endAnimation() {
  1128. if (mAnimationEndRequested) {
  1129. return;
  1130. }
  1131. removeAnimationCallback();
  1132. mAnimationEndRequested = true;
  1133. mPaused = false;
  1134. boolean notify = (mStarted || mRunning) && mListeners != null;
  1135. if (notify && !mRunning) {
  1136. // If it's not yet running, then start listeners weren't called. Call them now.
  1137. notifyStartListeners();
  1138. }
  1139. mRunning = false;
  1140. mStarted = false;
  1141. mStartListenersCalled = false;
  1142. mLastFrameTime = -1;
  1143. mFirstFrameTime = -1;
  1144. mStartTime = -1;
  1145. if (notify && mListeners != null) {
  1146. ArrayList<AnimatorListener> tmpListeners =
  1147. (ArrayList<AnimatorListener>) mListeners.clone();
  1148. int numListeners = tmpListeners.size();
  1149. for (int i = 0; i < numListeners; ++i) {
  1150. tmpListeners.get(i).onAnimationEnd(this, mReversing);
  1151. }
  1152. }
  1153. // mReversing needs to be reset *after* notifying the listeners for the end callbacks.
  1154. mReversing = false;
  1155. if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
  1156. Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
  1157. System.identityHashCode(this));
  1158. }
  1159. }
  1160. /**
  1161. * Called internally to start an animation by adding it to the active animations list. Must be
  1162. * called on the UI thread.
  1163. */
  1164. private void startAnimation() {
  1165. if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
  1166. Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
  1167. System.identityHashCode(this));
  1168. }
  1169. mAnimationEndRequested = false;
  1170. initAnimation();
  1171. mRunning = true;
  1172. if (mSeekFraction >= 0) {
  1173. mOverallFraction = mSeekFraction;
  1174. } else {
  1175. mOverallFraction = 0f;
  1176. }
  1177. if (mListeners != null) {
  1178. notifyStartListeners();
  1179. }
  1180. }
  1181. /**
  1182. * Internal only: This tracks whether the animation has gotten on the animation loop. Note
  1183. * this is different than {@link #isRunning()} in that the latter tracks the time after start()
  1184. * is called (or after start delay if any), which may be before the animation loop starts.
  1185. */
  1186. private boolean isPulsingInternal() {
  1187. return mLastFrameTime >= 0;
  1188. }
  1189. /**
  1190. * Returns the name of this animator for debugging purposes.
  1191. */
  1192. String getNameForTrace() {
  1193. return "animator";
  1194. }
  1195. /**
  1196. * Applies an adjustment to the animation to compensate for jank between when
  1197. * the animation first ran and when the frame was drawn.
  1198. * @hide
  1199. */
  1200. public void commitAnimationFrame(long frameTime) {
  1201. if (!mStartTimeCommitted) {
  1202. mStartTimeCommitted = true;
  1203. long adjustment = frameTime - mLastFrameTime;
  1204. if (adjustment > 0) {
  1205. mStartTime += adjustment;
  1206. if (DEBUG) {
  1207. Log.d(TAG, "Adjusted start time by " + adjustment + " ms: " + toString());
  1208. }
  1209. }
  1210. }
  1211. }
  1212. /**
  1213. * This internal function processes a single animation frame for a given animation. The
  1214. * currentTime parameter is the timing pulse sent by the handler, used to calculate the
  1215. * elapsed duration, and therefore
  1216. * the elapsed fraction, of the animation. The return value indicates whether the animation
  1217. * should be ended (which happens when the elapsed time of the animation exceeds the
  1218. * animation's duration, including the repeatCount).
  1219. *
  1220. * @param currentTime The current time, as tracked by the static timing handler
  1221. * @return true if the animation's duration, including any repetitions due to
  1222. * <code>repeatCount</code> has been exceeded and the animation should be ended.
  1223. */
  1224. boolean animateBasedOnTime(long currentTime) {
  1225. boolean done = false;
  1226. if (mRunning) {
  1227. final long scaledDuration = getScaledDuration();
  1228. final float fraction = scaledDuration > 0 ?
  1229. (float)(currentTime - mStartTime) / scaledDuration : 1f;
  1230. final float lastFraction = mOverallFraction;
  1231. final boolean newIteration = (int) fraction > (int) lastFraction;
  1232. final boolean lastIterationFinished = (fraction >= mRepeatCount + 1) &&
  1233. (mRepeatCount != INFINITE);
  1234. if (scaledDuration == 0) {
  1235. // 0 duration animator, ignore the repeat count and skip to the end
  1236. done = true;
  1237. } else if (newIteration && !lastIterationFinished) {
  1238. // Time to repeat
  1239. if (mListeners != null) {
  1240. int numListeners = mListeners.size();
  1241. for (int i = 0; i < numListeners; ++i) {
  1242. mListeners.get(i).onAnimationRepeat(this);
  1243. }
  1244. }
  1245. } else if (lastIterationFinished) {
  1246. done = true;
  1247. }
  1248. mOverallFraction = clampFraction(fraction);
  1249. float currentIterationFraction = getCurrentIterationFraction(
  1250. mOverallFraction, mReversing);
  1251. animateValue(currentIterationFraction);
  1252. }
  1253. return done;
  1254. }
  1255. /**
  1256. * Internal use only.
  1257. *
  1258. * This method does not modify any fields of the animation. It should be called when seeking
  1259. * in an AnimatorSet. When the last play time and current play time are of different repeat
  1260. * iterations,
  1261. * {@link android.view.animation.Animation.AnimationListener#onAnimationRepeat(Animation)}
  1262. * will be called.
  1263. */
  1264. @Override
  1265. void animateBasedOnPlayTime(long currentPlayTime, long lastPlayTime, boolean inReverse) {
  1266. if (currentPlayTime < 0 || lastPlayTime < 0) {
  1267. throw new UnsupportedOperationException("Error: Play time should never be negative.");
  1268. }
  1269. initAnimation();
  1270. // Check whether repeat callback is needed only when repeat count is non-zero
  1271. if (mRepeatCount > 0) {
  1272. int iteration = (int) (currentPlayTime / mDuration);
  1273. int lastIteration = (int) (lastPlayTime / mDuration);
  1274. // Clamp iteration to [0, mRepeatCount]
  1275. iteration = Math.min(iteration, mRepeatCount);
  1276. lastIteration = Math.min(lastIteration, mRepeatCount);
  1277. if (iteration != lastIteration) {
  1278. if (mListeners != null) {
  1279. int numListeners = mListeners.size();
  1280. for (int i = 0; i < numListeners; ++i) {
  1281. mListeners.get(i).onAnimationRepeat(this);
  1282. }
  1283. }
  1284. }
  1285. }
  1286. if (mRepeatCount != INFINITE && currentPlayTime >= (mRepeatCount + 1) * mDuration) {
  1287. skipToEndValue(inReverse);
  1288. } else {
  1289. // Find the current fraction:
  1290. float fraction = currentPlayTime / (float) mDuration;
  1291. fraction = getCurrentIterationFraction(fraction, inReverse);
  1292. animateValue(fraction);
  1293. }
  1294. }
  1295. /**
  1296. * Internal use only.
  1297. * Skips the animation value to end/start, depending on whether the play direction is forward
  1298. * or backward.
  1299. *
  1300. * @param inReverse whether the end value is based on a reverse direction. If yes, this is
  1301. * equivalent to skip to start value in a forward playing direction.
  1302. */
  1303. void skipToEndValue(boolean inReverse) {
  1304. initAnimation();
  1305. float endFraction = inReverse ? 0f : 1f;
  1306. if (mRepeatCount % 2 == 1 && mRepeatMode == REVERSE) {
  1307. // This would end on fraction = 0
  1308. endFraction = 0f;
  1309. }
  1310. animateValue(endFraction);
  1311. }
  1312. @Override
  1313. boolean isInitialized() {
  1314. return mInitialized;
  1315. }
  1316. /**
  1317. * Processes a frame of the animation, adjusting the start time if needed.
  1318. *
  1319. * @param frameTime The frame time.
  1320. * @return true if the animation has ended.
  1321. * @hide
  1322. */
  1323. public final boolean doAnimationFrame(long frameTime) {
  1324. if (mStartTime < 0) {
  1325. // First frame. If there is start delay, start delay count down will happen *after* this
  1326. // frame.
  1327. mStartTime = mReversing
  1328. ? frameTime
  1329. : frameTime + (long) (mStartDelay * resolveDurationScale());
  1330. }
  1331. // Handle pause/resume
  1332. if (mPaused) {
  1333. mPauseTime = frameTime;
  1334. removeAnimationCallback();
  1335. return false;
  1336. } else if (mResumed) {
  1337. mResumed = false;
  1338. if (mPauseTime > 0) {
  1339. // Offset by the duration that the animation was paused
  1340. mStartTime += (frameTime - mPauseTime);
  1341. }
  1342. }
  1343. if (!mRunning) {
  1344. // If not running, that means the animation is in the start delay phase of a forward
  1345. // running animation. In the case of reversing, we want to run start delay in the end.
  1346. if (mStartTime > frameTime && mSeekFraction == -1) {
  1347. // This is when no seek fraction is set during start delay. If developers change the
  1348. // seek fraction during the delay, animation will start from the seeked position
  1349. // right away.
  1350. return false;
  1351. } else {
  1352. // If mRunning is not set by now, that means non-zero start delay,
  1353. // no seeking, not reversing. At this point, start delay has passed.
  1354. mRunning = true;
  1355. startAnimation();
  1356. }
  1357. }
  1358. if (mLastFrameTime < 0) {
  1359. if (mSeekFraction >= 0) {
  1360. long seekTime = (long) (getScaledDuration() * mSeekFraction);
  1361. mStartTime = frameTime - seekTime;
  1362. mSeekFraction = -1;
  1363. }
  1364. mStartTimeCommitted = false; // allow start time to be compensated for jank
  1365. }
  1366. mLastFrameTime = frameTime;
  1367. // The frame time might be before the start time during the first frame of
  1368. // an animation. The "current time" must always be on or after the start
  1369. // time to avoid animating frames at negative time intervals. In practice, this
  1370. // is very rare and only happens when seeking backwards.
  1371. final long currentTime = Math.max(frameTime, mStartTime);
  1372. boolean finished = animateBasedOnTime(currentTime);
  1373. if (finished) {
  1374. endAnimation();
  1375. }
  1376. return finished;
  1377. }
  1378. @Override
  1379. boolean pulseAnimationFrame(long frameTime) {
  1380. if (mSelfPulse) {
  1381. // Pulse animation frame will *always* be after calling start(). If mSelfPulse isn't
  1382. // set to false at this point, that means child animators did not call super's start().
  1383. // This can happen when the Animator is just a non-animating wrapper around a real
  1384. // functional animation. In this case, we can't really pulse a frame into the animation,
  1385. // because the animation cannot necessarily be properly initialized (i.e. no start/end
  1386. // values set).
  1387. return false;
  1388. }
  1389. return doAnimationFrame(frameTime);
  1390. }
  1391. private void addOneShotCommitCallback() {
  1392. if (!mSelfPulse) {
  1393. return;
  1394. }
  1395. getAnimationHandler().addOneShotCommitCallback(this);
  1396. }
  1397. private void removeAnimationCallback() {
  1398. if (!mSelfPulse) {
  1399. return;
  1400. }
  1401. getAnimationHandler().removeCallback(this);
  1402. }
  1403. private void addAnimationCallback(long delay) {
  1404. if (!mSelfPulse) {
  1405. return;
  1406. }
  1407. getAnimationHandler().addAnimationFrameCallback(this, delay);
  1408. }
  1409. /**
  1410. * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
  1411. * the most recent frame update on the animation.
  1412. *
  1413. * @return Elapsed/interpolated fraction of the animation.
  1414. */
  1415. public float getAnimatedFraction() {
  1416. return mCurrentFraction;
  1417. }
  1418. /**
  1419. * This method is called with the elapsed fraction of the animation during every
  1420. * animation frame. This function turns the elapsed fraction into an interpolated fraction
  1421. * and then into an animated value (from the evaluator. The function is called mostly during
  1422. * animation updates, but it is also called when the <code>end()</code>
  1423. * function is called, to set the final value on the property.
  1424. *
  1425. * <p>Overrides of this method must call the superclass to perform the calculation
  1426. * of the animated value.</p>
  1427. *
  1428. * @param fraction The elapsed fraction of the animation.
  1429. */
  1430. @CallSuper
  1431. @UnsupportedAppUsage
  1432. void animateValue(float fraction) {
  1433. fraction = mInterpolator.getInterpolation(fraction);
  1434. mCurrentFraction = fraction;
  1435. int numValues = mValues.length;
  1436. for (int i = 0; i < numValues; ++i) {
  1437. mValues[i].calculateValue(fraction);
  1438. }
  1439. if (mUpdateListeners != null) {
  1440. int numListeners = mUpdateListeners.size();
  1441. for (int i = 0; i < numListeners; ++i) {
  1442. mUpdateListeners.get(i).onAnimationUpdate(this);
  1443. }
  1444. }
  1445. }
  1446. @Override
  1447. public ValueAnimator clone() {
  1448. final ValueAnimator anim = (ValueAnimator) super.clone();
  1449. if (mUpdateListeners != null) {
  1450. anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
  1451. }
  1452. anim.mSeekFraction = -1;
  1453. anim.mReversing = false;
  1454. anim.mInitialized = false;
  1455. anim.mStarted = false;
  1456. anim.mRunning = false;
  1457. anim.mPaused = false;
  1458. anim.mResumed = false;
  1459. anim.mStartListenersCalled = false;
  1460. anim.mStartTime = -1;
  1461. anim.mStartTimeCommitted = false;
  1462. anim.mAnimationEndRequested = false;
  1463. anim.mPauseTime = -1;
  1464. anim.mLastFrameTime = -1;
  1465. anim.mFirstFrameTime = -1;
  1466. anim.mOverallFraction = 0;
  1467. anim.mCurrentFraction = 0;
  1468. anim.mSelfPulse = true;
  1469. anim.mSuppressSelfPulseRequested = false;
  1470. PropertyValuesHolder[] oldValues = mValues;
  1471. if (oldValues != null) {
  1472. int numValues = oldValues.length;
  1473. anim.mValues = new PropertyValuesHolder[numValues];
  1474. anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
  1475. for (int i = 0; i < numValues; ++i) {
  1476. PropertyValuesHolder newValuesHolder = oldValues[i].clone();
  1477. anim.mValues[i] = newValuesHolder;
  1478. anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
  1479. }
  1480. }
  1481. return anim;
  1482. }
  1483. /**
  1484. * Implementors of this interface can add themselves as update listeners
  1485. * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
  1486. * frame, after the current frame's values have been calculated for that
  1487. * <code>ValueAnimator</code>.
  1488. */
  1489. public static interface AnimatorUpdateListener {
  1490. /**
  1491. * <p>Notifies the occurrence of another frame of the animation.</p>
  1492. *
  1493. * @param animation The animation which was repeated.
  1494. */
  1495. void onAnimationUpdate(ValueAnimator animation);
  1496. }
  1497. /**
  1498. * Return the number of animations currently running.
  1499. *
  1500. * Used by StrictMode internally to annotate violations.
  1501. * May be called on arbitrary threads!
  1502. *
  1503. * @hide
  1504. */
  1505. public static int getCurrentAnimationsCount() {
  1506. return AnimationHandler.getAnimationCount();
  1507. }
  1508. @Override
  1509. public String toString() {
  1510. String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
  1511. if (mValues != null) {
  1512. for (int i = 0; i < mValues.length; ++i) {
  1513. returnVal += "\n " + mValues[i].toString();
  1514. }
  1515. }
  1516. return returnVal;
  1517. }
  1518. /**
  1519. * <p>Whether or not the ValueAnimator is allowed to run asynchronously off of
  1520. * the UI thread. This is a hint that informs the ValueAnimator that it is
  1521. * OK to run the animation off-thread, however ValueAnimator may decide
  1522. * that it must run the animation on the UI thread anyway. For example if there
  1523. * is an {@link AnimatorUpdateListener} the animation will run on the UI thread,
  1524. * regardless of the value of this hint.</p>
  1525. *
  1526. * <p>Regardless of whether or not the animation runs asynchronously, all
  1527. * listener callbacks will be called on the UI thread.</p>
  1528. *
  1529. * <p>To be able to use this hint the following must be true:</p>
  1530. * <ol>
  1531. * <li>{@link #getAnimatedFraction()} is not needed (it will return undefined values).</li>
  1532. * <li>The animator is immutable while {@link #isStarted()} is true. Requests
  1533. * to change values, duration, delay, etc... may be ignored.</li>
  1534. * <li>Lifecycle callback events may be asynchronous. Events such as
  1535. * {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or
  1536. * {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed
  1537. * as they must be posted back to the UI thread, and any actions performed
  1538. * by those callbacks (such as starting new animations) will not happen
  1539. * in the same frame.</li>
  1540. * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...)
  1541. * may be asynchronous. It is guaranteed that all state changes that are
  1542. * performed on the UI thread in the same frame will be applied as a single
  1543. * atomic update, however that frame may be the current frame,
  1544. * the next frame, or some future frame. This will also impact the observed
  1545. * state of the Animator. For example, {@link #isStarted()} may still return true
  1546. * after a call to {@link #end()}. Using the lifecycle callbacks is preferred over
  1547. * queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()}
  1548. * for this reason.</li>
  1549. * </ol>
  1550. * @hide
  1551. */
  1552. @Override
  1553. public void setAllowRunningAsynchronously(boolean mayRunAsync) {
  1554. // It is up to subclasses to support this, if they can.
  1555. }
  1556. /**
  1557. * @return The {@link AnimationHandler} that will be used to schedule updates for this animator.
  1558. * @hide
  1559. */
  1560. public AnimationHandler getAnimationHandler() {
  1561. return mAnimationHandler != null ? mAnimationHandler : AnimationHandler.getInstance();
  1562. }
  1563. /**
  1564. * Sets the animation handler used to schedule updates for this animator or {@code null} to use
  1565. * the default handler.
  1566. * @hide
  1567. */
  1568. public void setAnimationHandler(@Nullable AnimationHandler animationHandler) {
  1569. mAnimationHandler = animationHandler;
  1570. }
  1571. }