ValueAnimator.java revision 7a08fe0e09c9bd5b66049738617cc9972651bf5b
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.animation; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powellimport android.os.Looper; 20c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powellimport android.os.Trace; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AndroidRuntimeException; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.Choreographer; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.AccelerateDecelerateInterpolator; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.AnimationUtils; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.animation.LinearInterpolator; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 272fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powellimport java.util.ArrayList; 28c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powellimport java.util.HashMap; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30fc94ddef2f8f56beebd848a73f434673d56631cbAdam Powell/** 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a simple timing engine for running animations 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * which calculate animated values and set them on target objects. 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>There is a single timing pulse that all animations use. It runs in a 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * custom handler to ensure that property changes happen on the UI thread.</p> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>By default, ValueAnimator uses non-linear time interpolation, via the 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * out of an animation. This behavior can be changed by calling 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p> 41c9006872800fceb1a5fef5e8f0470eb79953e79aAdam Powell * 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <div class="special reference"> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <h3>Developer Guides</h3> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>For more information about animating with {@code ValueAnimator}, read the 45c9006872800fceb1a5fef5e8f0470eb79953e79aAdam Powell * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property 46c9006872800fceb1a5fef5e8f0470eb79953e79aAdam Powell * Animation</a> developer guide.</p> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </div> 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project@SuppressWarnings("unchecked") 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ValueAnimator extends Animator { 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Internal constants 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static float sDurationScale = 1.0f; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 57558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez /** 58558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * Values used with internal variable mPlayingState to indicate the current state of an 59558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez * animation. 60558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez */ 61558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez static final int STOPPED = 0; // Not yet playing 62558459fe85f56f29a6ed6a4d0adb4a0bd6665884Joe Fernandez static final int RUNNING = 1; // Playing normally 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static final int SEEKED = 2; // Seeked to some time value 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Internal variables 67e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * NOTE: This object implements the clone() method, making a deep copy of any referenced 68e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * objects. As other non-trivial fields are added to this class, make sure to add logic 69e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * to clone() to make deep copies of them. 70e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 71e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 72e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn // The first time that the animation's animateFrame() method is called. This time is used to 73e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn // determine elapsed time (and therefore the elapsed fraction) in subsequent calls 74e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn // to animateFrame() 75e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn long mStartTime; 76e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 77e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn /** 78e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked 79e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * to a value. 80e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 81e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn long mSeekTime = -1; 82e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 83e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn /** 846e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * Set on the next frame after pause() is called, used to calculate a new startTime 856e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * or delayStartTime which allows the animator to continue from the point at which 866e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * it was paused. If negative, has not yet been set. 876e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell */ 886e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell private long mPauseTime; 896e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell 906e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell /** 916e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * Set when an animator is resumed. This triggers logic in the next frame which 926e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * actually resumes the animator. 936e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell */ 946e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell private boolean mResumed = false; 956e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell 96e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The static sAnimationHandler processes the internal timing loop on which all animations 98e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn // are based 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 101e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 102e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn protected static ThreadLocal<AnimationHandler> sAnimationHandler = 103e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn new ThreadLocal<AnimationHandler>(); 104e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 105e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn // The time interpolator to be used if none is set on the animation 106e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn private static final TimeInterpolator sDefaultInterpolator = 107e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn new AccelerateDecelerateInterpolator(); 108e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 110e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * Used to indicate whether the animation is currently playing in reverse. This causes the 111e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * elapsed fraction to be inverted to calculate the appropriate values. 112e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 113e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn private boolean mPlayingBackwards = false; 114e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 115cfaf8878de83b6bb7a24aee3c240259f428e6e4aDianne Hackborn /** 116e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * repeatCount (if repeatCount!=INFINITE), the animation ends 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mCurrentIteration = 0; 120e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 121cfaf8878de83b6bb7a24aee3c240259f428e6e4aDianne Hackborn /** 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction(). 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private float mCurrentFraction = 0f; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 127e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * Tracks whether a startDelay'd animation has begun playing through the startDelay. 128e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 129e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn private boolean mStartedDelay = false; 130e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 131e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn /** 132e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * Tracks the time at which the animation began playing through its startDelay. This is 133e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * different from the mStartTime variable, which is used to track when the animation became 1346e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * active (which is when the startDelay expired and the animation was added to the active 1356e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell * animations list). 1366e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell */ 1376e90a362bc66cc67b1beae27b21d3f0148403b08Adam Powell private long mDelayStartTime; 138e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn 139e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn /** 140e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * Flag that represents the current state of the animation. Used to figure out when to start 141e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * an animation (if state == STOPPED). Also used to end an animation that 142e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * has been cancel()'d or end()'d since the last animation frame. Possible values are 143e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * STOPPED, RUNNING, SEEKED. 144e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 145e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn int mPlayingState = STOPPED; 1462fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell 1472fbf4de64f0ec5052201cea9519c44d5b1789a40Adam Powell /** 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Additional playing state to indicate whether an animator has been start()'d. There is 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some lag between a call to start() and the first animation frame. We should still note 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that the animation has been started, even if it's first animation frame has not yet 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * happened, and reflect that state in isRunning(). 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Note that delayed animations are different: they are not started until their first 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * animation frame, which occurs after their delay elapses. 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mRunning = false; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Additional playing state to indicate whether an animator has been start()'d, whether or 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not there is a nonzero startDelay. 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mStarted = false; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Tracks whether we've notified listeners of the onAnimationStart() event. This can be 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * complex to keep track of since we notify listeners at different times depending on 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * startDelay and whether start() was called before end(). 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mStartListenersCalled = false; 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Flag that denotes whether the animation is set up and ready to go. Used to 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set up animation that has not yet been started. 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mInitialized = false; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Backing variables 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // How long the animation should last in ms 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mDuration = (long)(300 * sDurationScale); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mUnscaledDuration = 300; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The amount of time in ms to delay starting the animation after start() is called 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mStartDelay = 0; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long mUnscaledStartDelay = 0; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The number of times the animation will repeat. The default is 0, which means the animation 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // will play only once 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRepeatCount = 0; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The type of repetition that will occur when repeatMode is nonzero. RESTART means the 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * animation will start from the beginning on every new cycle. REVERSE means the animation 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will reverse directions on each iteration. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mRepeatMode = RESTART; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The time interpolator to be used. The elapsed fraction of the animation will be passed 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * through this interpolator to calculate the interpolated fraction, which is then used to 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * calculate the animated values. 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private TimeInterpolator mInterpolator = sDefaultInterpolator; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The set of listeners to be sent events through the life of an animation. 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<AnimatorUpdateListener> mUpdateListeners = null; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The property/value sets being animated. 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PropertyValuesHolder[] mValues; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by property name during calls to getAnimatedValue(String). 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project HashMap<String, PropertyValuesHolder> mValuesMap; 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Public constants 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When the animation reaches the end and <code>repeatCount</code> is INFINITE 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or a positive value, the animation restarts from the beginning. 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int RESTART = 1; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * When the animation reaches the end and <code>repeatCount</code> is INFINITE 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * or a positive value, the animation reverses direction on every iteration. 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int REVERSE = 2; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This value used used with the {@link #setRepeatCount(int)} property to repeat 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the animation indefinitely. 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int INFINITE = -1; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void setDurationScale(float durationScale) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sDurationScale = durationScale; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static float getDurationScale() { 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sDurationScale; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Creates a new ValueAnimator object. This default constructor is primarily for 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use internally; the factory methods which take parameters are more generally 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful. 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ValueAnimator() { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs and returns a ValueAnimator that animates between int values. A single 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting value for the animation (unlike ObjectAnimator, which can derive that value 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the target object and property being animated). Therefore, there should typically 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be two or more values. 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of values that the animation will animate between over time. 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A ValueAnimator object that is set up to animate between the given values. 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ValueAnimator ofInt(int... values) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = new ValueAnimator(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setIntValues(values); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return anim; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs and returns a ValueAnimator that animates between color values. A single 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting value for the animation (unlike ObjectAnimator, which can derive that value 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the target object and property being animated). Therefore, there should typically 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be two or more values. 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of values that the animation will animate between over time. 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A ValueAnimator object that is set up to animate between the given values. 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ValueAnimator ofArgb(int... values) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = new ValueAnimator(); 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setIntValues(values); 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setEvaluator(ArgbEvaluator.getInstance()); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return anim; 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs and returns a ValueAnimator that animates between float values. A single 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting value for the animation (unlike ObjectAnimator, which can derive that value 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the target object and property being animated). Therefore, there should typically 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be two or more values. 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of values that the animation will animate between over time. 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A ValueAnimator object that is set up to animate between the given values. 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ValueAnimator ofFloat(float... values) { 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = new ValueAnimator(); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setFloatValues(values); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return anim; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 318947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * Constructs and returns a ValueAnimator that animates between the values 319947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * specified in the PropertyValuesHolder objects. 320947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * 321947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * @param values A set of PropertyValuesHolder objects whose values will be animated 322947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * between over time. 323947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * @return A ValueAnimator object that is set up to animate between the given values. 324947f7824118f0e9b642df8760a8725a7eda59318Adam Powell */ 325947f7824118f0e9b642df8760a8725a7eda59318Adam Powell public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) { 326947f7824118f0e9b642df8760a8725a7eda59318Adam Powell ValueAnimator anim = new ValueAnimator(); 327947f7824118f0e9b642df8760a8725a7eda59318Adam Powell anim.setValues(values); 328947f7824118f0e9b642df8760a8725a7eda59318Adam Powell return anim; 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructs and returns a ValueAnimator that animates between Object values. A single 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting value for the animation (unlike ObjectAnimator, which can derive that value 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the target object and property being animated). Therefore, there should typically 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be two or more values. 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * factory method also takes a TypeEvaluator object that the ValueAnimator will use 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to perform that interpolation. 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param evaluator A TypeEvaluator that will be called on each animation frame to 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * provide the ncessry interpolation between the Object values to derive the animated 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value. 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of values that the animation will animate between over time. 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A ValueAnimator object that is set up to animate between the given values. 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = new ValueAnimator(); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setObjectValues(values); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.setEvaluator(evaluator); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return anim; 353e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts } 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets int values that will be animated between. A single 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 359e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * starting value for the animation (unlike ObjectAnimator, which can derive that value 360e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts * from the target object and property being animated). Therefore, there should typically 361e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts * be two or more values. 362e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts * 363e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts * <p>If there are already multiple sets of values defined for this ValueAnimator via more 364e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * than one PropertyValuesHolder object, this method will set the values for the first 365e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * of those objects.</p> 366e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * 367e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn * @param values A set of values that the animation will animate between over time. 368e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn */ 369e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn public void setIntValues(int... values) { 370e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn if (values == null || values.length == 0) { 371e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn return; 372e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts } 373e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts if (mValues == null || mValues.length == 0) { 374e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn setValues(PropertyValuesHolder.ofInt("", values)); 375e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn } else { 376e429c5ec9d52a5e9af9133f5de9f1002f04aede1Martin Nordholts PropertyValuesHolder valuesHolder = mValues[0]; 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project valuesHolder.setIntValues(values); 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // New property/values/target should cause re-initialization prior to starting 380c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell mInitialized = false; 381c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell } 382c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell 383c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell /** 384c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * Sets float values that will be animated between. A single 385c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * value implies that that value is the one being animated to. However, this is not typically 386c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * useful in a ValueAnimator object because there is no way for the object to determine the 387c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * starting value for the animation (unlike ObjectAnimator, which can derive that value 388ccb013ffac696df1cd1bfc528264e583d01c9ab5Adam Powell * from the target object and property being animated). Therefore, there should typically 389c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * be two or more values. 390c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * 391c49c17314d4b7f36e50a5b01edd6d4b13b940366Adam Powell * <p>If there are already multiple sets of values defined for this ValueAnimator via more 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * than one PropertyValuesHolder object, this method will set the values for the first 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of those objects.</p> 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values A set of values that the animation will animate between over time. 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setFloatValues(float... values) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (values == null || values.length == 0) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mValues == null || mValues.length == 0) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setValues(PropertyValuesHolder.ofFloat("", values)); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PropertyValuesHolder valuesHolder = mValues[0]; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project valuesHolder.setFloatValues(values); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // New property/values/target should cause re-initialization prior to starting 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInitialized = false; 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the values to animate between for this animation. A single 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value implies that that value is the one being animated to. However, this is not typically 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in a ValueAnimator object because there is no way for the object to determine the 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * starting value for the animation (unlike ObjectAnimator, which can derive that value 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * from the target object and property being animated). Therefore, there should typically 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be two or more values. 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If there are already multiple sets of values defined for this ValueAnimator via more 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * than one PropertyValuesHolder object, this method will set the values for the first 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * of those objects.</p> 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * between these value objects. ValueAnimator only knows how to interpolate between the 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * primitive types specified in the other setValues() methods.</p> 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values The set of values to animate between. 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setObjectValues(Object... values) { 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (values == null || values.length == 0) { 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mValues == null || mValues.length == 0) { 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setValues(PropertyValuesHolder.ofObject("", null, values)); 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PropertyValuesHolder valuesHolder = mValues[0]; 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project valuesHolder.setObjectValues(values); 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // New property/values/target should cause re-initialization prior to starting 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInitialized = false; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the values, per property, being animated between. This function is called internally 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be constructed without values and this method can be called to set the values manually 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * instead. 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param values The set of values, per property, being animated between. 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setValues(PropertyValuesHolder... values) { 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numValues = values.length; 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValues = values; 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numValues; ++i) { 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PropertyValuesHolder valuesHolder = values[i]; 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // New property/values/target should cause re-initialization prior to starting 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInitialized = false; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the values that this ValueAnimator animates between. These values are stored in 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list 466947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * of value objects instead. 467947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * 468947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the 469947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * values, per property, that define the animation. 470947f7824118f0e9b642df8760a8725a7eda59318Adam Powell */ 471947f7824118f0e9b642df8760a8725a7eda59318Adam Powell public PropertyValuesHolder[] getValues() { 472947f7824118f0e9b642df8760a8725a7eda59318Adam Powell return mValues; 473947f7824118f0e9b642df8760a8725a7eda59318Adam Powell } 474947f7824118f0e9b642df8760a8725a7eda59318Adam Powell 475947f7824118f0e9b642df8760a8725a7eda59318Adam Powell /** 476947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * This function is called immediately before processing the first animation 477947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * frame of an animation. If there is a nonzero <code>startDelay</code>, the 478947f7824118f0e9b642df8760a8725a7eda59318Adam Powell * function is called after that delay ends. 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * It takes care of the final initialization steps for the 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * animation. 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>Overrides of this method should call the superclass method to ensure 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that internal mechanisms for the animation are set up correctly.</p> 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void initAnimation() { 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mInitialized) { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numValues = mValues.length; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numValues; ++i) { 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mValues[i].init(); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInitialized = true; 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the length of the animation. The default duration is 300 milliseconds. 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param duration The length of the animation, in milliseconds. This value cannot 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be negative. 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return ValueAnimator The object called with setDuration(). This return 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * value makes it easier to compose statements together that construct and then set the 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>. 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ValueAnimator setDuration(long duration) { 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration < 0) { 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalArgumentException("Animators cannot have negative duration: " + 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration); 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUnscaledDuration = duration; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project updateScaledDuration(); 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return this; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void updateScaledDuration() { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDuration = (long)(mUnscaledDuration * sDurationScale); 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the length of the animation. The default duration is 300 milliseconds. 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The length of the animation, in milliseconds. 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getDuration() { 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mUnscaledDuration; 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the position of the animation to the specified point in time. This time should 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be between 0 and the total duration of the animation, including any repetition. If 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the animation has not yet been started, then it will not advance forward after it is 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set to this time; it will simply set the time to this value and perform any appropriate 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * actions based on that time. If the animation is already running, then setCurrentPlayTime() 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will set the current playing time to this value and continue playing from that point. 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param playTime The time, in milliseconds, to which the animation is advanced or rewound. 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setCurrentPlayTime(long playTime) { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project initAnimation(); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long currentTime = AnimationUtils.currentAnimationTimeMillis(); 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mPlayingState != RUNNING) { 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mSeekTime = playTime; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPlayingState = SEEKED; 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartTime = currentTime - playTime; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project doAnimationFrame(currentTime); 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the current position of the animation in time, which is equal to the current 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * time minus the time that the animation started. An animation that is not yet started will 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * return a value of zero. 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The current position in time of the animation. 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getCurrentPlayTime() { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mInitialized || mPlayingState == STOPPED) { 55869ea4e15e52c456537575d21443ac1efdb03a902Brad Fitzpatrick return 0; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AnimationUtils.currentAnimationTimeMillis() - mStartTime; 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This custom, static handler handles the timing pulse that is shared by 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * all active animations. This approach ensures that the setting of animation 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * values will happen on the UI thread and that all animations will share 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the same times for calculating their values, which makes synchronizing 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * animations possible. 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The handler uses the Choreographer for executing periodic callbacks. 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @SuppressWarnings("unchecked") 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected static class AnimationHandler implements Runnable { 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The per-thread list of all active animations 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>(); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>(); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The per-thread set of animations to be started on the next animation frame 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** @hide */ 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>(); 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Internal per-thread collections used to avoid set collisions as animations start and end 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * while being processed. 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>(); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>(); 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>(); 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Choreographer mChoreographer; 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean mAnimationScheduled; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private AnimationHandler() { 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChoreographer = Choreographer.getInstance(); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start animating on the next frame. 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void start() { 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scheduleAnimation(); 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void doAnimationFrame(long frameTime) { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // mPendingAnimations holds any animations that have requested to be started 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // We're going to clear mPendingAnimations, but starting animation may 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // cause more to be added to the pending list (for example, if one animation 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // starting triggers another starting). So we loop until mPendingAnimations 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // is empty. 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (mPendingAnimations.size() > 0) { 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ValueAnimator> pendingCopy = 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (ArrayList<ValueAnimator>) mPendingAnimations.clone(); 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mPendingAnimations.clear(); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int count = pendingCopy.size(); 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < count; ++i) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = pendingCopy.get(i); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If the animation has a startDelay, place it on the delayed list 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (anim.mStartDelay == 0) { 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.startAnimation(this); 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDelayedAnims.add(anim); 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Next, process animations currently sitting on the delayed queue, adding 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // them to the active animations if they are ready 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numDelayedAnims = mDelayedAnims.size(); 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numDelayedAnims; ++i) { 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = mDelayedAnims.get(i); 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (anim.delayedAnimationFrame(frameTime)) { 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReadyAnims.add(anim); 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numReadyAnims = mReadyAnims.size(); 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (numReadyAnims > 0) { 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numReadyAnims; ++i) { 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = mReadyAnims.get(i); 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.startAnimation(this); 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project anim.mRunning = true; 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mDelayedAnims.remove(anim); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mReadyAnims.clear(); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Now process all active animations. The return value from animationFrame() 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // tells the handler whether it should now be ended 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numAnims = mAnimations.size(); 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numAnims; ++i) { 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTmpAnimations.add(mAnimations.get(i)); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numAnims; ++i) { 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ValueAnimator anim = mTmpAnimations.get(i); 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) { 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEndingAnims.add(anim); 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mTmpAnimations.clear(); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mEndingAnims.size() > 0) { 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < mEndingAnims.size(); ++i) { 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEndingAnims.get(i).endAnimation(this); 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mEndingAnims.clear(); 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If there are still active or delayed animations, schedule a future call to 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // onAnimate to process the next frame of the animations. 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scheduleAnimation(); 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Called by the Choreographer. 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAnimationScheduled = false; 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project doAnimationFrame(mChoreographer.getFrameTime()); 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void scheduleAnimation() { 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!mAnimationScheduled) { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null); 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAnimationScheduled = true; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The amount of time, in milliseconds, to delay starting the animation after 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #start()} is called. 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of milliseconds to delay running the animation 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getStartDelay() { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mUnscaledStartDelay; 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The amount of time, in milliseconds, to delay starting the animation after 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #start()} is called. 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param startDelay The amount of the delay, in milliseconds 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setStartDelay(long startDelay) { 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.mStartDelay = (long)(startDelay * sDurationScale); 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUnscaledStartDelay = startDelay; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The amount of time, in milliseconds, between each frame of the animation. This is a 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * requested time that the animation will attempt to honor, but the actual delay between 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * frames may be different, depending on system load and capabilities. This is a static 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * function because the same delay will be applied to all animations, since they are all 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * run off of a single timing loop. 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The frame delay may be ignored when the animation system uses an external timing 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * source, such as the display refresh rate (vsync), to govern animations. 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the requested time between frames, in milliseconds 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getFrameDelay() { 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return Choreographer.getFrameDelay(); 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The amount of time, in milliseconds, between each frame of the animation. This is a 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * requested time that the animation will attempt to honor, but the actual delay between 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * frames may be different, depending on system load and capabilities. This is a static 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * function because the same delay will be applied to all animations, since they are all 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * run off of a single timing loop. 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The frame delay may be ignored when the animation system uses an external timing 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * source, such as the display refresh rate (vsync), to govern animations. 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param frameDelay the requested time between frames, in milliseconds 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void setFrameDelay(long frameDelay) { 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Choreographer.setFrameDelay(frameDelay); 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The most recent value calculated by this <code>ValueAnimator</code> when there is just one 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * property being animated. This value is only sensible while the animation is running. The main 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code> 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is called during each animation frame, immediately after the value is calculated. 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the single property being animated. If there are several properties being animated 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (specified by several PropertyValuesHolder objects in the constructor), this function 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returns the animated value for the first of those objects. 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object getAnimatedValue() { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mValues != null && mValues.length > 0) { 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mValues[0].getAnimatedValue(); 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Shouldn't get here; should always have values unless ValueAnimator was set up wrong 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>. 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The main purpose for this read-only property is to retrieve the value from the 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>ValueAnimator</code> during a call to 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is called during each animation frame, immediately after the value is calculated. 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return animatedValue The value most recently calculated for the named property 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * by this <code>ValueAnimator</code>. 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Object getAnimatedValue(String propertyName) { 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (valuesHolder != null) { 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return valuesHolder.getAnimatedValue(); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // At least avoid crashing if called with bogus propertyName 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return null; 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets how many times the animation should be repeated. If the repeat 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * count is 0, the animation is never repeated. If the repeat count is 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * greater than 0 or {@link #INFINITE}, the repeat mode will be taken 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * into account. The repeat count is 0 by default. 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the number of times the animation should be repeated 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRepeatCount(int value) { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRepeatCount = value; 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines how many times the animation should repeat. The default value 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is 0. 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the number of times the animation should repeat, or {@link #INFINITE} 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRepeatCount() { 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mRepeatCount; 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines what this animation should do when it reaches the end. This 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * setting is applied only when the repeat count is either greater than 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value {@link #RESTART} or {@link #REVERSE} 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setRepeatMode(int value) { 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mRepeatMode = value; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Defines what this animation should do when it reaches the end. 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return either one of {@link #REVERSE} or {@link #RESTART} 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getRepeatMode() { 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mRepeatMode; 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Adds a listener to the set of listeners that are sent update events through the life of 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * an animation. This method is called on all listeners for every frame of the animation, 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * after the values for the animation have been calculated. 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener to be added to the current set of listeners for this animation. 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void addUpdateListener(AnimatorUpdateListener listener) { 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdateListeners == null) { 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners.add(listener); 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Removes all listeners from the set listening to frame updates for this animation. 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeAllUpdateListeners() { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdateListeners == null) { 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners.clear(); 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners = null; 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Removes a listener from the set listening to frame updates for this animation. 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param listener the listener to be removed from the current set of update listeners 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for this animation. 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void removeUpdateListener(AnimatorUpdateListener listener) { 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdateListeners == null) { 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners.remove(listener); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mUpdateListeners.size() == 0) { 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mUpdateListeners = null; 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 868935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn 869935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn /** 870935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn * The time interpolator used in calculating the elapsed fraction of this animation. The 871935ae463d495d41155e27feb849768ad2b8b16dbDianne Hackborn * interpolator determines whether the animation runs with linear or non-linear motion, 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * such as acceleration and deceleration. The default value is 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.animation.AccelerateDecelerateInterpolator} 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the interpolator to be used by this animation. A value of <code>null</code> 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will result in linear interpolation. 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setInterpolator(TimeInterpolator value) { 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null) { 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInterpolator = value; 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mInterpolator = new LinearInterpolator(); 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the timing interpolator that this ValueAnimator uses. 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The timing interpolator for this ValueAnimator. 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public TimeInterpolator getInterpolator() { 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mInterpolator; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8969c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy 8979c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy /** 8989c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * The type evaluator to be used when calculating the animated values of this animation. 8999c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * The system will automatically assign a float or int evaluator based on the type 9009c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values 9019c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * are not one of these primitive types, or if different evaluation is desired (such as is 9029c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * necessary with int values that represent colors), a custom evaluator needs to be assigned. 9039c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * For example, when running an animation on color values, the {@link ArgbEvaluator} 9049c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * should be used to get correct RGB color interpolation. 9059c802c1e95befbd8de30ea4ebc48ae05cb948b2bRomain Guy * 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>If this ValueAnimator has only one set of values being animated between, this evaluator 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be used for that set. If there are several sets of values being animated, which is 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the case if PropertyValuesHolder objects were set on the ValueAnimator, then the evaluator 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is assigned just to the first PropertyValuesHolder object.</p> 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param value the evaluator to be used this animation 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 913e79b55482eb3f26d6d5b56dce40682dd68826f8cDianne Hackborn public void setEvaluator(TypeEvaluator value) { 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (value != null && mValues != null && mValues.length > 0) { 915fbca76965b96b31a8974e461ee1929867ef3327bAdam Powell mValues[0].setEvaluator(value); 916fbca76965b96b31a8974e461ee1929867ef3327bAdam Powell } 917fbca76965b96b31a8974e461ee1929867ef3327bAdam Powell } 918fbca76965b96b31a8974e461ee1929867ef3327bAdam Powell 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void notifyStartListeners() { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mListeners != null && !mStartListenersCalled) { 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<AnimatorListener> tmpListeners = 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (ArrayList<AnimatorListener>) mListeners.clone(); 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int numListeners = tmpListeners.size(); 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < numListeners; ++i) { 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project tmpListeners.get(i).onAnimationStart(this); 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mStartListenersCalled = true; 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Start the animation playing. This version of start() takes a boolean flag that indicates 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * whether the animation should play in reverse. The flag is usually false, but may be set 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to true if called from the reverse() method. 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p>The animation started by calling this method will be run on the thread that called 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * this method. This thread should have a Looper on it (a runtime exception will be thrown if 938 * this is not the case). Also, if the animation will animate 939 * properties of objects in the view hierarchy, then the calling thread should be the UI 940 * thread for that view hierarchy.</p> 941 * 942 * @param playBackwards Whether the ValueAnimator should start playing in reverse. 943 */ 944 private void start(boolean playBackwards) { 945 if (Looper.myLooper() == null) { 946 throw new AndroidRuntimeException("Animators may only be run on Looper threads"); 947 } 948 mPlayingBackwards = playBackwards; 949 mCurrentIteration = 0; 950 mPlayingState = STOPPED; 951 mStarted = true; 952 mStartedDelay = false; 953 mPaused = false; 954 updateScaledDuration(); // in case the scale factor has changed since creation time 955 AnimationHandler animationHandler = getOrCreateAnimationHandler(); 956 animationHandler.mPendingAnimations.add(this); 957 if (mStartDelay == 0) { 958 // This sets the initial value of the animation, prior to actually starting it running 959 setCurrentPlayTime(0); 960 mPlayingState = STOPPED; 961 mRunning = true; 962 notifyStartListeners(); 963 } 964 animationHandler.start(); 965 } 966 967 @Override 968 public void start() { 969 start(false); 970 } 971 972 @Override 973 public void cancel() { 974 // Only cancel if the animation is actually running or has been started and is about 975 // to run 976 AnimationHandler handler = getOrCreateAnimationHandler(); 977 if (mPlayingState != STOPPED 978 || handler.mPendingAnimations.contains(this) 979 || handler.mDelayedAnims.contains(this)) { 980 // Only notify listeners if the animator has actually started 981 if ((mStarted || mRunning) && mListeners != null) { 982 if (!mRunning) { 983 // If it's not yet running, then start listeners weren't called. Call them now. 984 notifyStartListeners(); 985 } 986 ArrayList<AnimatorListener> tmpListeners = 987 (ArrayList<AnimatorListener>) mListeners.clone(); 988 for (AnimatorListener listener : tmpListeners) { 989 listener.onAnimationCancel(this); 990 } 991 } 992 endAnimation(handler); 993 } 994 } 995 996 @Override 997 public void end() { 998 AnimationHandler handler = getOrCreateAnimationHandler(); 999 if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) { 1000 // Special case if the animation has not yet started; get it ready for ending 1001 mStartedDelay = false; 1002 startAnimation(handler); 1003 mStarted = true; 1004 } else if (!mInitialized) { 1005 initAnimation(); 1006 } 1007 animateValue(mPlayingBackwards ? 0f : 1f); 1008 endAnimation(handler); 1009 } 1010 1011 @Override 1012 public void resume() { 1013 if (mPaused) { 1014 mResumed = true; 1015 } 1016 super.resume(); 1017 } 1018 1019 @Override 1020 public void pause() { 1021 boolean previouslyPaused = mPaused; 1022 super.pause(); 1023 if (!previouslyPaused && mPaused) { 1024 mPauseTime = -1; 1025 mResumed = false; 1026 } 1027 } 1028 1029 @Override 1030 public boolean isRunning() { 1031 return (mPlayingState == RUNNING || mRunning); 1032 } 1033 1034 @Override 1035 public boolean isStarted() { 1036 return mStarted; 1037 } 1038 1039 /** 1040 * Plays the ValueAnimator in reverse. If the animation is already running, 1041 * it will stop itself and play backwards from the point reached when reverse was called. 1042 * If the animation is not currently running, then it will start from the end and 1043 * play backwards. This behavior is only set for the current animation; future playing 1044 * of the animation will use the default behavior of playing forward. 1045 */ 1046 @Override 1047 public void reverse() { 1048 mPlayingBackwards = !mPlayingBackwards; 1049 if (mPlayingState == RUNNING) { 1050 long currentTime = AnimationUtils.currentAnimationTimeMillis(); 1051 long currentPlayTime = currentTime - mStartTime; 1052 long timeLeft = mDuration - currentPlayTime; 1053 mStartTime = currentTime - timeLeft; 1054 } else if (mStarted) { 1055 end(); 1056 } else { 1057 start(true); 1058 } 1059 } 1060 1061 /** 1062 * @hide 1063 */ 1064 @Override 1065 public boolean canReverse() { 1066 return true; 1067 } 1068 1069 /** 1070 * Called internally to end an animation by removing it from the animations list. Must be 1071 * called on the UI thread. 1072 * @hide 1073 */ 1074 protected void endAnimation(AnimationHandler handler) { 1075 handler.mAnimations.remove(this); 1076 handler.mPendingAnimations.remove(this); 1077 handler.mDelayedAnims.remove(this); 1078 mPlayingState = STOPPED; 1079 mPaused = false; 1080 if ((mStarted || mRunning) && mListeners != null) { 1081 if (!mRunning) { 1082 // If it's not yet running, then start listeners weren't called. Call them now. 1083 notifyStartListeners(); 1084 } 1085 ArrayList<AnimatorListener> tmpListeners = 1086 (ArrayList<AnimatorListener>) mListeners.clone(); 1087 int numListeners = tmpListeners.size(); 1088 for (int i = 0; i < numListeners; ++i) { 1089 tmpListeners.get(i).onAnimationEnd(this); 1090 } 1091 } 1092 mRunning = false; 1093 mStarted = false; 1094 mStartListenersCalled = false; 1095 mPlayingBackwards = false; 1096 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 1097 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(), 1098 System.identityHashCode(this)); 1099 } 1100 } 1101 1102 /** 1103 * Called internally to start an animation by adding it to the active animations list. Must be 1104 * called on the UI thread. 1105 */ 1106 private void startAnimation(AnimationHandler handler) { 1107 if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { 1108 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(), 1109 System.identityHashCode(this)); 1110 } 1111 initAnimation(); 1112 handler.mAnimations.add(this); 1113 if (mStartDelay > 0 && mListeners != null) { 1114 // Listeners were already notified in start() if startDelay is 0; this is 1115 // just for delayed animations 1116 notifyStartListeners(); 1117 } 1118 } 1119 1120 /** 1121 * Returns the name of this animator for debugging purposes. 1122 */ 1123 String getNameForTrace() { 1124 return "animator"; 1125 } 1126 1127 1128 /** 1129 * Internal function called to process an animation frame on an animation that is currently 1130 * sleeping through its <code>startDelay</code> phase. The return value indicates whether it 1131 * should be woken up and put on the active animations queue. 1132 * 1133 * @param currentTime The current animation time, used to calculate whether the animation 1134 * has exceeded its <code>startDelay</code> and should be started. 1135 * @return True if the animation's <code>startDelay</code> has been exceeded and the animation 1136 * should be added to the set of active animations. 1137 */ 1138 private boolean delayedAnimationFrame(long currentTime) { 1139 if (!mStartedDelay) { 1140 mStartedDelay = true; 1141 mDelayStartTime = currentTime; 1142 } 1143 if (mPaused) { 1144 if (mPauseTime < 0) { 1145 mPauseTime = currentTime; 1146 } 1147 return false; 1148 } else if (mResumed) { 1149 mResumed = false; 1150 if (mPauseTime > 0) { 1151 // Offset by the duration that the animation was paused 1152 mDelayStartTime += (currentTime - mPauseTime); 1153 } 1154 } 1155 long deltaTime = currentTime - mDelayStartTime; 1156 if (deltaTime > mStartDelay) { 1157 // startDelay ended - start the anim and record the 1158 // mStartTime appropriately 1159 mStartTime = currentTime - (deltaTime - mStartDelay); 1160 mPlayingState = RUNNING; 1161 return true; 1162 } 1163 return false; 1164 } 1165 1166 /** 1167 * This internal function processes a single animation frame for a given animation. The 1168 * currentTime parameter is the timing pulse sent by the handler, used to calculate the 1169 * elapsed duration, and therefore 1170 * the elapsed fraction, of the animation. The return value indicates whether the animation 1171 * should be ended (which happens when the elapsed time of the animation exceeds the 1172 * animation's duration, including the repeatCount). 1173 * 1174 * @param currentTime The current time, as tracked by the static timing handler 1175 * @return true if the animation's duration, including any repetitions due to 1176 * <code>repeatCount</code>, has been exceeded and the animation should be ended. 1177 */ 1178 boolean animationFrame(long currentTime) { 1179 boolean done = false; 1180 switch (mPlayingState) { 1181 case RUNNING: 1182 case SEEKED: 1183 float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f; 1184 if (fraction >= 1f) { 1185 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { 1186 // Time to repeat 1187 if (mListeners != null) { 1188 int numListeners = mListeners.size(); 1189 for (int i = 0; i < numListeners; ++i) { 1190 mListeners.get(i).onAnimationRepeat(this); 1191 } 1192 } 1193 if (mRepeatMode == REVERSE) { 1194 mPlayingBackwards = !mPlayingBackwards; 1195 } 1196 mCurrentIteration += (int)fraction; 1197 fraction = fraction % 1f; 1198 mStartTime += mDuration; 1199 } else { 1200 done = true; 1201 fraction = Math.min(fraction, 1.0f); 1202 } 1203 } 1204 if (mPlayingBackwards) { 1205 fraction = 1f - fraction; 1206 } 1207 animateValue(fraction); 1208 break; 1209 } 1210 1211 return done; 1212 } 1213 1214 /** 1215 * Processes a frame of the animation, adjusting the start time if needed. 1216 * 1217 * @param frameTime The frame time. 1218 * @return true if the animation has ended. 1219 */ 1220 final boolean doAnimationFrame(long frameTime) { 1221 if (mPlayingState == STOPPED) { 1222 mPlayingState = RUNNING; 1223 if (mSeekTime < 0) { 1224 mStartTime = frameTime; 1225 } else { 1226 mStartTime = frameTime - mSeekTime; 1227 // Now that we're playing, reset the seek time 1228 mSeekTime = -1; 1229 } 1230 } 1231 if (mPaused) { 1232 if (mPauseTime < 0) { 1233 mPauseTime = frameTime; 1234 } 1235 return false; 1236 } else if (mResumed) { 1237 mResumed = false; 1238 if (mPauseTime > 0) { 1239 // Offset by the duration that the animation was paused 1240 mStartTime += (frameTime - mPauseTime); 1241 } 1242 } 1243 // The frame time might be before the start time during the first frame of 1244 // an animation. The "current time" must always be on or after the start 1245 // time to avoid animating frames at negative time intervals. In practice, this 1246 // is very rare and only happens when seeking backwards. 1247 final long currentTime = Math.max(frameTime, mStartTime); 1248 return animationFrame(currentTime); 1249 } 1250 1251 /** 1252 * Returns the current animation fraction, which is the elapsed/interpolated fraction used in 1253 * the most recent frame update on the animation. 1254 * 1255 * @return Elapsed/interpolated fraction of the animation. 1256 */ 1257 public float getAnimatedFraction() { 1258 return mCurrentFraction; 1259 } 1260 1261 /** 1262 * This method is called with the elapsed fraction of the animation during every 1263 * animation frame. This function turns the elapsed fraction into an interpolated fraction 1264 * and then into an animated value (from the evaluator. The function is called mostly during 1265 * animation updates, but it is also called when the <code>end()</code> 1266 * function is called, to set the final value on the property. 1267 * 1268 * <p>Overrides of this method must call the superclass to perform the calculation 1269 * of the animated value.</p> 1270 * 1271 * @param fraction The elapsed fraction of the animation. 1272 */ 1273 void animateValue(float fraction) { 1274 fraction = mInterpolator.getInterpolation(fraction); 1275 mCurrentFraction = fraction; 1276 int numValues = mValues.length; 1277 for (int i = 0; i < numValues; ++i) { 1278 mValues[i].calculateValue(fraction); 1279 } 1280 if (mUpdateListeners != null) { 1281 int numListeners = mUpdateListeners.size(); 1282 for (int i = 0; i < numListeners; ++i) { 1283 mUpdateListeners.get(i).onAnimationUpdate(this); 1284 } 1285 } 1286 } 1287 1288 @Override 1289 public ValueAnimator clone() { 1290 final ValueAnimator anim = (ValueAnimator) super.clone(); 1291 if (mUpdateListeners != null) { 1292 ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners; 1293 anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); 1294 int numListeners = oldListeners.size(); 1295 for (int i = 0; i < numListeners; ++i) { 1296 anim.mUpdateListeners.add(oldListeners.get(i)); 1297 } 1298 } 1299 anim.mSeekTime = -1; 1300 anim.mPlayingBackwards = false; 1301 anim.mCurrentIteration = 0; 1302 anim.mInitialized = false; 1303 anim.mPlayingState = STOPPED; 1304 anim.mStartedDelay = false; 1305 PropertyValuesHolder[] oldValues = mValues; 1306 if (oldValues != null) { 1307 int numValues = oldValues.length; 1308 anim.mValues = new PropertyValuesHolder[numValues]; 1309 anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); 1310 for (int i = 0; i < numValues; ++i) { 1311 PropertyValuesHolder newValuesHolder = oldValues[i].clone(); 1312 anim.mValues[i] = newValuesHolder; 1313 anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder); 1314 } 1315 } 1316 return anim; 1317 } 1318 1319 /** 1320 * Implementors of this interface can add themselves as update listeners 1321 * to an <code>ValueAnimator</code> instance to receive callbacks on every animation 1322 * frame, after the current frame's values have been calculated for that 1323 * <code>ValueAnimator</code>. 1324 */ 1325 public static interface AnimatorUpdateListener { 1326 /** 1327 * <p>Notifies the occurrence of another frame of the animation.</p> 1328 * 1329 * @param animation The animation which was repeated. 1330 */ 1331 void onAnimationUpdate(ValueAnimator animation); 1332 1333 } 1334 1335 /** 1336 * Return the number of animations currently running. 1337 * 1338 * Used by StrictMode internally to annotate violations. 1339 * May be called on arbitrary threads! 1340 * 1341 * @hide 1342 */ 1343 public static int getCurrentAnimationsCount() { 1344 AnimationHandler handler = sAnimationHandler.get(); 1345 return handler != null ? handler.mAnimations.size() : 0; 1346 } 1347 1348 /** 1349 * Clear all animations on this thread, without canceling or ending them. 1350 * This should be used with caution. 1351 * 1352 * @hide 1353 */ 1354 public static void clearAllAnimations() { 1355 AnimationHandler handler = sAnimationHandler.get(); 1356 if (handler != null) { 1357 handler.mAnimations.clear(); 1358 handler.mPendingAnimations.clear(); 1359 handler.mDelayedAnims.clear(); 1360 } 1361 } 1362 1363 private static AnimationHandler getOrCreateAnimationHandler() { 1364 AnimationHandler handler = sAnimationHandler.get(); 1365 if (handler == null) { 1366 handler = new AnimationHandler(); 1367 sAnimationHandler.set(handler); 1368 } 1369 return handler; 1370 } 1371 1372 @Override 1373 public String toString() { 1374 String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode()); 1375 if (mValues != null) { 1376 for (int i = 0; i < mValues.length; ++i) { 1377 returnVal += "\n " + mValues[i].toString(); 1378 } 1379 } 1380 return returnVal; 1381 } 1382 1383 /** 1384 * <p>Whether or not the ValueAnimator is allowed to run asynchronously off of 1385 * the UI thread. This is a hint that informs the ValueAnimator that it is 1386 * OK to run the animation off-thread, however ValueAnimator may decide 1387 * that it must run the animation on the UI thread anyway. For example if there 1388 * is an {@link AnimatorUpdateListener} the animation will run on the UI thread, 1389 * regardless of the value of this hint.</p> 1390 * 1391 * <p>Regardless of whether or not the animation runs asynchronously, all 1392 * listener callbacks will be called on the UI thread.</p> 1393 * 1394 * <p>To be able to use this hint the following must be true:</p> 1395 * <ol> 1396 * <li>{@link #getAnimatedFraction()} is not needed (it will return undefined values).</li> 1397 * <li>The animator is immutable while {@link #isStarted()} is true. Requests 1398 * to change values, duration, delay, etc... may be ignored.</li> 1399 * <li>Lifecycle callback events may be asynchronous. Events such as 1400 * {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or 1401 * {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed 1402 * as they must be posted back to the UI thread, and any actions performed 1403 * by those callbacks (such as starting new animations) will not happen 1404 * in the same frame.</li> 1405 * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...) 1406 * may be asynchronous. It is guaranteed that all state changes that are 1407 * performed on the UI thread in the same frame will be applied as a single 1408 * atomic update, however that frame may be the current frame, 1409 * the next frame, or some future frame. This will also impact the observed 1410 * state of the Animator. For example, {@link #isStarted()} may still return true 1411 * after a call to {@link #end()}. Using the lifecycle callbacks is preferred over 1412 * queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()} 1413 * for this reason.</li> 1414 * </ol> 1415 * @hide 1416 */ 1417 @Override 1418 public void setAllowRunningAsynchronously(boolean mayRunAsync) { 1419 // It is up to subclasses to support this, if they can. 1420 } 1421} 1422