diff options
author | Chet Haase <chet@google.com> | 2010-09-07 13:20:00 -0700 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2010-09-08 09:41:21 -0700 |
commit | a18a86b43e40e3c15dcca0ae0148d641be9b25fe (patch) | |
tree | 80f115b33fa69994f3cf7347d77c3463d1eda439 /core/java/android | |
parent | 789a47488c0e834eb80fe6b596dcc3e0ba7f1344 (diff) | |
download | frameworks_base-a18a86b43e40e3c15dcca0ae0148d641be9b25fe.zip frameworks_base-a18a86b43e40e3c15dcca0ae0148d641be9b25fe.tar.gz frameworks_base-a18a86b43e40e3c15dcca0ae0148d641be9b25fe.tar.bz2 |
Rename several animation classes
Change-Id: I6a4544875090db485163c8d56de8718f56d267c7
Diffstat (limited to 'core/java/android')
17 files changed, 1430 insertions, 1440 deletions
diff --git a/core/java/android/animation/Animatable.java b/core/java/android/animation/Animatable.java deleted file mode 100644 index 3fdf200..0000000 --- a/core/java/android/animation/Animatable.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.animation; - -import android.view.animation.Interpolator; - -import java.util.ArrayList; - -/** - * This is the superclass for classes which provide basic support for animations which can be - * started, ended, and have <code>AnimatableListeners</code> added to them. - */ -public abstract class Animatable implements Cloneable { - - - /** - * The set of listeners to be sent events through the life of an animation. - */ - ArrayList<AnimatableListener> mListeners = null; - - /** - * Starts this animation. If the animation has a nonzero startDelay, the animation will start - * running after that delay elapses. Note that the animation does not start synchronously with - * this call, because all animation events are posted to a central timing loop so that animation - * times are all synchronized on a single timing pulse on the UI thread. So the animation will - * start the next time that event handler processes events. - */ - public void start() { - } - - /** - * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to - * stop in its tracks, sending an {@link AnimatableListener#onAnimationCancel(Animatable)} to - * its listeners, followed by an {@link AnimatableListener#onAnimationEnd(Animatable)} message. - */ - public void cancel() { - } - - /** - * Ends the animation. This causes the animation to assign the end value of the property being - * animated, then calling the {@link AnimatableListener#onAnimationEnd(Animatable)} method on - * its listeners. - */ - public void end() { - } - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - * - * @return the number of milliseconds to delay running the animation - */ - public abstract long getStartDelay(); - - /** - * The amount of time, in milliseconds, to delay starting the animation after - * {@link #start()} is called. - - * @param startDelay The amount of the delay, in milliseconds - */ - public abstract void setStartDelay(long startDelay); - - - /** - * Sets the length of the animation. - * - * @param duration The length of the animation, in milliseconds. - */ - public abstract void setDuration(long duration); - - /** - * Gets the length of the animation. - * - * @return The length of the animation, in milliseconds. - */ - public abstract long getDuration(); - - /** - * The time interpolator used in calculating the elapsed fraction of this animation. The - * interpolator determines whether the animation runs with linear or non-linear motion, - * such as acceleration and deceleration. The default value is - * {@link android.view.animation.AccelerateDecelerateInterpolator} - * - * @param value the interpolator to be used by this animation - */ - public abstract void setInterpolator(Interpolator value); - - /** - * Returns whether this Animatable is currently running (having been started and not yet ended). - * @return Whether the Animatable is running. - */ - public abstract boolean isRunning(); - - /** - * Adds a listener to the set of listeners that are sent events through the life of an - * animation, such as start, repeat, and end. - * - * @param listener the listener to be added to the current set of listeners for this animation. - */ - public void addListener(AnimatableListener listener) { - if (mListeners == null) { - mListeners = new ArrayList<AnimatableListener>(); - } - mListeners.add(listener); - } - - /** - * Removes a listener from the set listening to this animation. - * - * @param listener the listener to be removed from the current set of listeners for this - * animation. - */ - public void removeListener(AnimatableListener listener) { - if (mListeners == null) { - return; - } - mListeners.remove(listener); - if (mListeners.size() == 0) { - mListeners = null; - } - } - - /** - * Gets the set of {@link AnimatableListener} objects that are currently - * listening for events on this <code>Animatable</code> object. - * - * @return ArrayList<AnimatableListener> The set of listeners. - */ - public ArrayList<AnimatableListener> getListeners() { - return mListeners; - } - - /** - * Removes all listeners from this object. This is equivalent to calling - * <code>getListeners()</code> followed by calling <code>clear()</code> on the - * returned list of listeners. - */ - public void removeAllListeners() { - if (mListeners != null) { - mListeners.clear(); - mListeners = null; - } - } - - @Override - public Animatable clone() { - try { - final Animatable anim = (Animatable) super.clone(); - if (mListeners != null) { - ArrayList<AnimatableListener> oldListeners = mListeners; - anim.mListeners = new ArrayList<AnimatableListener>(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mListeners.add(oldListeners.get(i)); - } - } - return anim; - } catch (CloneNotSupportedException e) { - throw new AssertionError(); - } - } - - /** - * This method tells the object to use appropriate information to extract - * starting values for the animation. For example, a Sequencer object will pass - * this call to its child objects to tell them to set up the values. A - * PropertyAnimator object will use the information it has about its target object - * and PropertyValuesHolder objects to get the start values for its properties. - * An Animator object will ignore the request since it does not have enough - * information (such as a target object) to gather these values. - */ - public void setupStartValues() { - } - - /** - * This method tells the object to use appropriate information to extract - * ending values for the animation. For example, a Sequencer object will pass - * this call to its child objects to tell them to set up the values. A - * PropertyAnimator object will use the information it has about its target object - * and PropertyValuesHolder objects to get the start values for its properties. - * An Animator object will ignore the request since it does not have enough - * information (such as a target object) to gather these values. - */ - public void setupEndValues() { - } - - /** - * Sets the target object whose property will be animated by this animation. Not all subclasses - * operate on target objects (for example, {@link android.animation.Animator}, but this method - * is on the superclass for the convenience of dealing generically with those subclasses - * that do handle targets. - * - * @param target The object being animated - */ - public void setTarget(Object target) { - } - - /** - * <p>An animation listener receives notifications from an animation. - * Notifications indicate animation related events, such as the end or the - * repetition of the animation.</p> - */ - public static interface AnimatableListener { - /** - * <p>Notifies the start of the animation.</p> - * - * @param animation The started animation. - */ - void onAnimationStart(Animatable animation); - - /** - * <p>Notifies the end of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.</p> - * - * @param animation The animation which reached its end. - */ - void onAnimationEnd(Animatable animation); - - /** - * <p>Notifies the cancellation of the animation. This callback is not invoked - * for animations with repeat count set to INFINITE.</p> - * - * @param animation The animation which was canceled. - */ - void onAnimationCancel(Animatable animation); - - /** - * <p>Notifies the repetition of the animation.</p> - * - * @param animation The animation which was repeated. - */ - void onAnimationRepeat(Animatable animation); - } -} diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index 8e947ec..2ada6d6 100755..100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -16,461 +16,46 @@ package android.animation; -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import java.util.ArrayList; -import java.util.HashMap; /** - * This class provides a simple timing engine for running animations - * which calculate animated values and set them on target objects. - * - * <p>There is a single timing pulse that all animations use. It runs in a - * custom handler to ensure that property changes happen on the UI thread.</p> - * - * <p>By default, Animator uses non-linear time interpolation, via the - * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates - * out of an animation. This behavior can be changed by calling - * {@link Animator#setInterpolator(Interpolator)}.</p> + * This is the superclass for classes which provide basic support for animations which can be + * started, ended, and have <code>AnimatorListeners</code> added to them. */ -public class Animator<T> extends Animatable { - - /** - * Internal constants - */ - - /* - * The default amount of time in ms between animation frames - */ - private static final long DEFAULT_FRAME_DELAY = 30; - - /** - * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent - * by the handler to itself to process the next animation frame - */ - private static final int ANIMATION_START = 0; - private static final int ANIMATION_FRAME = 1; - - /** - * Values used with internal variable mPlayingState to indicate the current state of an - * animation. - */ - private static final int STOPPED = 0; // Not yet playing - private static final int RUNNING = 1; // Playing normally - private static final int CANCELED = 2; // cancel() called - need to end it - private static final int ENDED = 3; // end() called - need to end it - private static final int SEEKED = 4; // Seeked to some time value - - /** - * Internal variables - * NOTE: This object implements the clone() method, making a deep copy of any referenced - * objects. As other non-trivial fields are added to this class, make sure to add logic - * to clone() to make deep copies of them. - */ - - // The first time that the animation's animateFrame() method is called. This time is used to - // determine elapsed time (and therefore the elapsed fraction) in subsequent calls - // to animateFrame() - private long mStartTime; - - /** - * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked - * to a value. - */ - private long mSeekTime = -1; - - // The static sAnimationHandler processes the internal timing loop on which all animations - // are based - private static AnimationHandler sAnimationHandler; - - // The static list of all active animations - private static final ArrayList<Animator> sAnimations = new ArrayList<Animator>(); - - // The set of animations to be started on the next animation frame - private static final ArrayList<Animator> sPendingAnimations = new ArrayList<Animator>(); - - // The time interpolator to be used if none is set on the animation - private static final Interpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); - - // type evaluators for the three primitive types handled by this implementation - private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); - private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); - private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator(); - - /** - * Used to indicate whether the animation is currently playing in reverse. This causes the - * elapsed fraction to be inverted to calculate the appropriate values. - */ - private boolean mPlayingBackwards = false; - - /** - * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the - * repeatCount (if repeatCount!=INFINITE), the animation ends - */ - private int mCurrentIteration = 0; - - /** - * Tracks whether a startDelay'd animation has begun playing through the startDelay. - */ - private boolean mStartedDelay = false; - - /** - * Tracks the time at which the animation began playing through its startDelay. This is - * different from the mStartTime variable, which is used to track when the animation became - * active (which is when the startDelay expired and the animation was added to the active - * animations list). - */ - private long mDelayStartTime; - - /** - * Flag that represents the current state of the animation. Used to figure out when to start - * an animation (if state == STOPPED). Also used to end an animation that - * has been cancel()'d or end()'d since the last animation frame. Possible values are - * STOPPED, RUNNING, ENDED, CANCELED. - */ - private int mPlayingState = STOPPED; - - /** - * Internal collections used to avoid set collisions as animations start and end while being - * processed. - */ - private static final ArrayList<Animator> sEndingAnims = new ArrayList<Animator>(); - private static final ArrayList<Animator> sDelayedAnims = new ArrayList<Animator>(); - private static final ArrayList<Animator> sReadyAnims = new ArrayList<Animator>(); - - /** - * Flag that denotes whether the animation is set up and ready to go. Used to - * set up animation that has not yet been started. - */ - boolean mInitialized = false; - - // - // Backing variables - // - - // How long the animation should last in ms - private long mDuration; - - // The amount of time in ms to delay starting the animation after start() is called - private long mStartDelay = 0; - - // The number of milliseconds between animation frames - private static long sFrameDelay = DEFAULT_FRAME_DELAY; +public abstract class Animator implements Cloneable { - // The number of times the animation will repeat. The default is 0, which means the animation - // will play only once - private int mRepeatCount = 0; - - /** - * The type of repetition that will occur when repeatMode is nonzero. RESTART means the - * animation will start from the beginning on every new cycle. REVERSE means the animation - * will reverse directions on each iteration. - */ - private int mRepeatMode = RESTART; - - /** - * The time interpolator to be used. The elapsed fraction of the animation will be passed - * through this interpolator to calculate the interpolated fraction, which is then used to - * calculate the animated values. - */ - private Interpolator mInterpolator = sDefaultInterpolator; /** * The set of listeners to be sent events through the life of an animation. */ - private ArrayList<AnimatorUpdateListener> mUpdateListeners = null; - - /** - * The property/value sets being animated. - */ - PropertyValuesHolder[] mValues; - - /** - * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values - * by property name during calls to getAnimatedValue(String). - */ - HashMap<String, PropertyValuesHolder> mValuesMap; - - /** - * Public constants - */ - - /** - * When the animation reaches the end and <code>repeatCount</code> is INFINITE - * or a positive value, the animation restarts from the beginning. - */ - public static final int RESTART = 1; - /** - * When the animation reaches the end and <code>repeatCount</code> is INFINITE - * or a positive value, the animation reverses direction on every iteration. - */ - public static final int REVERSE = 2; - /** - * This value used used with the {@link #setRepeatCount(int)} property to repeat - * the animation indefinitely. - */ - public static final int INFINITE = -1; - - /** - * Creates a new Animator object. This default constructor is primarily for - * use internally; the other constructors which take parameters are more generally - * useful. - */ - public Animator() { - } - - /** - * Constructs an Animator object with the specified duration and set of - * values. If the values are a set of PropertyValuesHolder objects, then these objects - * define the potentially multiple properties being animated and the values the properties are - * animated between. Otherwise, the values define a single set of values animated between. - * - * @param duration The length of the animation, in milliseconds. - * @param values The set of values to animate between. If these values are not - * PropertyValuesHolder objects, then there should be more than one value, since the values - * determine the interval to animate between. - */ - public Animator(long duration, T...values) { - mDuration = duration; - if (values.length > 0) { - setValues(values); - } - } - - /** - * Sets the values, per property, being animated between. This function is called internally - * by the constructors of Animator that take a list of values. But an Animator can - * be constructed without values and this method can be called to set the values manually - * instead. - * - * @param values The set of values, per property, being animated between. - */ - public void setValues(PropertyValuesHolder... values) { - int numValues = values.length; - mValues = values; - mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); - for (int i = 0; i < numValues; ++i) { - PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i]; - mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); - } - } - - /** - * Returns the values that this Animator animates between. These values are stored in - * PropertyValuesHolder objects, even if the Animator was created with a simple list - * of value objects instead. - * - * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the - * values, per property, that define the animation. - */ - public PropertyValuesHolder[] getValues() { - return mValues; - } - - /** - * Sets the values to animate between for this animation. If <code>values</code> is - * a set of PropertyValuesHolder objects, these objects will become the set of properties - * animated and the values that those properties are animated between. Otherwise, this method - * will set only one set of values for the Animator. Also, if the values are not - * PropertyValuesHolder objects and if there are already multiple sets of - * values defined for this Animator via - * more than one PropertyValuesHolder objects, this method will set the values for - * the first of those objects. - * - * @param values The set of values to animate between. - */ - public void setValues(T... values) { - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{ - new PropertyValuesHolder("", (Object[])values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setValues(values); - } - } - - /** - * This function is called immediately before processing the first animation - * frame of an animation. If there is a nonzero <code>startDelay</code>, the - * function is called after that delay ends. - * It takes care of the final initialization steps for the - * animation. - * - * <p>Overrides of this method should call the superclass method to ensure - * that internal mechanisms for the animation are set up correctly.</p> - */ - void initAnimation() { - if (!mInitialized) { - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].init(); - } - mCurrentIteration = 0; - mInitialized = true; - } - } - + ArrayList<AnimatorListener> mListeners = null; /** - * Sets the length of the animation. - * - * @param duration The length of the animation, in milliseconds. + * Starts this animation. If the animation has a nonzero startDelay, the animation will start + * running after that delay elapses. Note that the animation does not start synchronously with + * this call, because all animation events are posted to a central timing loop so that animation + * times are all synchronized on a single timing pulse on the UI thread. So the animation will + * start the next time that event handler processes events. */ - public void setDuration(long duration) { - mDuration = duration; - } - - /** - * Gets the length of the animation. - * - * @return The length of the animation, in milliseconds. - */ - public long getDuration() { - return mDuration; - } - - /** - * Sets the position of the animation to the specified point in time. This time should - * be between 0 and the total duration of the animation, including any repetition. If - * the animation has not yet been started, then it will not advance forward after it is - * set to this time; it will simply set the time to this value and perform any appropriate - * actions based on that time. If the animation is already running, then setCurrentPlayTime() - * will set the current playing time to this value and continue playing from that point. - * - * @param playTime The time, in milliseconds, to which the animation is advanced or rewound. - */ - public void setCurrentPlayTime(long playTime) { - initAnimation(); - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - if (mPlayingState != RUNNING) { - mSeekTime = playTime; - mPlayingState = SEEKED; - } - mStartTime = currentTime - playTime; - animationFrame(currentTime); + public void start() { } /** - * Gets the current position of the animation in time, which is equal to the current - * time minus the time that the animation started. An animation that is not yet started will - * return a value of zero. - * - * @return The current position in time of the animation. + * Cancels the animation. Unlike {@link #end()}, <code>cancel()</code> causes the animation to + * stop in its tracks, sending an {@link android.animation.Animator.AnimatorListener#onAnimationCancel(Animator)} to + * its listeners, followed by an {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} message. */ - public long getCurrentPlayTime() { - if (!mInitialized || mPlayingState == STOPPED) { - return 0; - } - return AnimationUtils.currentAnimationTimeMillis() - mStartTime; + public void cancel() { } /** - * This custom, static handler handles the timing pulse that is shared by - * all active animations. This approach ensures that the setting of animation - * values will happen on the UI thread and that all animations will share - * the same times for calculating their values, which makes synchronizing - * animations possible. - * + * Ends the animation. This causes the animation to assign the end value of the property being + * animated, then calling the {@link android.animation.Animator.AnimatorListener#onAnimationEnd(Animator)} method on + * its listeners. */ - private static class AnimationHandler extends Handler { - /** - * There are only two messages that we care about: ANIMATION_START and - * ANIMATION_FRAME. The START message is sent when an animation's start() - * method is called. It cannot start synchronously when start() is called - * because the call may be on the wrong thread, and it would also not be - * synchronized with other animations because it would not start on a common - * timing pulse. So each animation sends a START message to the handler, which - * causes the handler to place the animation on the active animations queue and - * start processing frames for that animation. - * The FRAME message is the one that is sent over and over while there are any - * active animations to process. - */ - @Override - public void handleMessage(Message msg) { - boolean callAgain = true; - switch (msg.what) { - // TODO: should we avoid sending frame message when starting if we - // were already running? - case ANIMATION_START: - if (sAnimations.size() > 0 || sDelayedAnims.size() > 0) { - callAgain = false; - } - // pendingAnims holds any animations that have requested to be started - // We're going to clear sPendingAnimations, but starting animation may - // cause more to be added to the pending list (for example, if one animation - // starting triggers another starting). So we loop until sPendingAnimations - // is empty. - while (sPendingAnimations.size() > 0) { - ArrayList<Animator> pendingCopy = - (ArrayList<Animator>) sPendingAnimations.clone(); - sPendingAnimations.clear(); - int count = pendingCopy.size(); - for (int i = 0; i < count; ++i) { - Animator anim = pendingCopy.get(i); - // If the animation has a startDelay, place it on the delayed list - if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED || - anim.mPlayingState == CANCELED) { - anim.startAnimation(); - } else { - sDelayedAnims.add(anim); - } - } - } - // fall through to process first frame of new animations - case ANIMATION_FRAME: - // currentTime holds the common time for all animations processed - // during this frame - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - - // First, process animations currently sitting on the delayed queue, adding - // them to the active animations if they are ready - int numDelayedAnims = sDelayedAnims.size(); - for (int i = 0; i < numDelayedAnims; ++i) { - Animator anim = sDelayedAnims.get(i); - if (anim.delayedAnimationFrame(currentTime)) { - sReadyAnims.add(anim); - } - } - int numReadyAnims = sReadyAnims.size(); - if (numReadyAnims > 0) { - for (int i = 0; i < numReadyAnims; ++i) { - Animator anim = sReadyAnims.get(i); - anim.startAnimation(); - sDelayedAnims.remove(anim); - } - sReadyAnims.clear(); - } - - // Now process all active animations. The return value from animationFrame() - // tells the handler whether it should now be ended - int numAnims = sAnimations.size(); - for (int i = 0; i < numAnims; ++i) { - Animator anim = sAnimations.get(i); - if (anim.animationFrame(currentTime)) { - sEndingAnims.add(anim); - } - } - if (sEndingAnims.size() > 0) { - for (int i = 0; i < sEndingAnims.size(); ++i) { - sEndingAnims.get(i).endAnimation(); - } - sEndingAnims.clear(); - } - - // If there are still active or delayed animations, call the handler again - // after the frameDelay - if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) { - sendEmptyMessageDelayed(ANIMATION_FRAME, sFrameDelay); - } - break; - } - } + public void end() { } /** @@ -479,9 +64,7 @@ public class Animator<T> extends Animatable { * * @return the number of milliseconds to delay running the animation */ - public long getStartDelay() { - return mStartDelay; - } + public abstract long getStartDelay(); /** * The amount of time, in milliseconds, to delay starting the animation after @@ -489,485 +72,177 @@ public class Animator<T> extends Animatable { * @param startDelay The amount of the delay, in milliseconds */ - public void setStartDelay(long startDelay) { - this.mStartDelay = startDelay; - } + public abstract void setStartDelay(long startDelay); - /** - * The amount of time, in milliseconds, between each frame of the animation. This is a - * requested time that the animation will attempt to honor, but the actual delay between - * frames may be different, depending on system load and capabilities. This is a static - * function because the same delay will be applied to all animations, since they are all - * run off of a single timing loop. - * - * @return the requested time between frames, in milliseconds - */ - public static long getFrameDelay() { - return sFrameDelay; - } - - /** - * The amount of time, in milliseconds, between each frame of the animation. This is a - * requested time that the animation will attempt to honor, but the actual delay between - * frames may be different, depending on system load and capabilities. This is a static - * function because the same delay will be applied to all animations, since they are all - * run off of a single timing loop. - * - * @param frameDelay the requested time between frames, in milliseconds - */ - public static void setFrameDelay(long frameDelay) { - sFrameDelay = frameDelay; - } /** - * The most recent value calculated by this <code>Animator</code> when there is just one - * property being animated. This value is only sensible while the animation is running. The main - * purpose for this read-only property is to retrieve the value from the <code>Animator</code> - * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(Animator)}, which - * is called during each animation frame, immediately after the value is calculated. - * - * @return animatedValue The value most recently calculated by this <code>Animator</code> for - * the single property being animated. If there are several properties being animated - * (specified by several PropertyValuesHolder objects in the constructor), this function - * returns the animated value for the first of those objects. - */ - public Object getAnimatedValue() { - if (mValues != null && mValues.length > 0) { - return mValues[0].getAnimatedValue(); - } - // Shouldn't get here; should always have values unless Animator was set up wrong - return null; - } - - /** - * The most recent value calculated by this <code>Animator</code> for <code>propertyName</code>. - * The main purpose for this read-only property is to retrieve the value from the - * <code>Animator</code> during a call to - * {@link AnimatorUpdateListener#onAnimationUpdate(Animator)}, which - * is called during each animation frame, immediately after the value is calculated. + * Sets the length of the animation. * - * @return animatedValue The value most recently calculated for the named property - * by this <code>Animator</code>. + * @param duration The length of the animation, in milliseconds. */ - public Object getAnimatedValue(String propertyName) { - PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); - if (valuesHolder != null) { - return valuesHolder.getAnimatedValue(); - } else { - // At least avoid crashing if called with bogus propertyName - return null; - } - } + public abstract void setDuration(long duration); /** - * Sets how many times the animation should be repeated. If the repeat - * count is 0, the animation is never repeated. If the repeat count is - * greater than 0 or {@link #INFINITE}, the repeat mode will be taken - * into account. The repeat count is 0 by default. - * - * @param value the number of times the animation should be repeated - */ - public void setRepeatCount(int value) { - mRepeatCount = value; - } - /** - * Defines how many times the animation should repeat. The default value - * is 0. + * Gets the length of the animation. * - * @return the number of times the animation should repeat, or {@link #INFINITE} + * @return The length of the animation, in milliseconds. */ - public int getRepeatCount() { - return mRepeatCount; - } + public abstract long getDuration(); /** - * Defines what this animation should do when it reaches the end. This - * setting is applied only when the repeat count is either greater than - * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. + * The time interpolator used in calculating the elapsed fraction of this animation. The + * interpolator determines whether the animation runs with linear or non-linear motion, + * such as acceleration and deceleration. The default value is + * {@link android.view.animation.AccelerateDecelerateInterpolator} * - * @param value {@link #RESTART} or {@link #REVERSE} + * @param value the interpolator to be used by this animation */ - public void setRepeatMode(int value) { - mRepeatMode = value; - } + public abstract void setInterpolator(Interpolator value); /** - * Defines what this animation should do when it reaches the end. - * - * @return either one of {@link #REVERSE} or {@link #RESTART} + * Returns whether this Animator is currently running (having been started and not yet ended). + * @return Whether the Animator is running. */ - public int getRepeatMode() { - return mRepeatMode; - } + public abstract boolean isRunning(); /** - * Adds a listener to the set of listeners that are sent update events through the life of - * an animation. This method is called on all listeners for every frame of the animation, - * after the values for the animation have been calculated. + * Adds a listener to the set of listeners that are sent events through the life of an + * animation, such as start, repeat, and end. * * @param listener the listener to be added to the current set of listeners for this animation. */ - public void addUpdateListener(AnimatorUpdateListener listener) { - if (mUpdateListeners == null) { - mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); + public void addListener(AnimatorListener listener) { + if (mListeners == null) { + mListeners = new ArrayList<AnimatorListener>(); } - mUpdateListeners.add(listener); + mListeners.add(listener); } /** - * Removes a listener from the set listening to frame updates for this animation. + * Removes a listener from the set listening to this animation. * - * @param listener the listener to be removed from the current set of update listeners - * for this animation. + * @param listener the listener to be removed from the current set of listeners for this + * animation. */ - public void removeUpdateListener(AnimatorUpdateListener listener) { - if (mUpdateListeners == null) { + public void removeListener(AnimatorListener listener) { + if (mListeners == null) { return; } - mUpdateListeners.remove(listener); - if (mUpdateListeners.size() == 0) { - mUpdateListeners = null; + mListeners.remove(listener); + if (mListeners.size() == 0) { + mListeners = null; } } - /** - * The time interpolator used in calculating the elapsed fraction of this animation. The - * interpolator determines whether the animation runs with linear or non-linear motion, - * such as acceleration and deceleration. The default value is - * {@link android.view.animation.AccelerateDecelerateInterpolator} + * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently + * listening for events on this <code>Animator</code> object. * - * @param value the interpolator to be used by this animation + * @return ArrayList<AnimatorListener> The set of listeners. */ - @Override - public void setInterpolator(Interpolator value) { - if (value != null) { - mInterpolator = value; - } + public ArrayList<AnimatorListener> getListeners() { + return mListeners; } /** - * Returns the timing interpolator that this Animator uses. - * - * @return The timing interpolator for this Animator. + * Removes all listeners from this object. This is equivalent to calling + * <code>getListeners()</code> followed by calling <code>clear()</code> on the + * returned list of listeners. */ - public Interpolator getInterpolator() { - return mInterpolator; - } - - /** - * The type evaluator to be used when calculating the animated values of this animation. - * The system will automatically assign a float, int, or double evaluator based on the type - * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values - * are not one of these primitive types, or if different evaluation is desired (such as is - * necessary with int values that represent colors), a custom evaluator needs to be assigned. - * For example, when running an animation on color values, the {@link RGBEvaluator} - * should be used to get correct RGB color interpolation. - * - * <p>If this Animator has only one set of values being animated between, this evaluator - * will be used for that set. If there are several sets of values being animated, which is - * the case if PropertyValuesHOlder objects were set on the Animator, then the evaluator - * is assigned just to the first PropertyValuesHolder object.</p> - * - * @param value the evaluator to be used this animation - */ - public void setEvaluator(TypeEvaluator value) { - if (value != null && mValues != null && mValues.length > 0) { - mValues[0].setEvaluator(value); - } - } - - /** - * Start the animation playing. This version of start() takes a boolean flag that indicates - * whether the animation should play in reverse. The flag is usually false, but may be set - * to true if called from the reverse() method/ - * - * @param playBackwards Whether the Animator should start playing in reverse. - */ - private void start(boolean playBackwards) { - mPlayingBackwards = playBackwards; - if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) { - // This sets the initial value of the animation, prior to actually starting it running - setCurrentPlayTime(getCurrentPlayTime()); - } - mPlayingState = STOPPED; - mStartedDelay = false; - sPendingAnimations.add(this); - if (sAnimationHandler == null) { - sAnimationHandler = new AnimationHandler(); - } - // TODO: does this put too many messages on the queue if the handler - // is already running? - sAnimationHandler.sendEmptyMessage(ANIMATION_START); - } - - @Override - public void start() { - start(false); - } - - @Override - public void cancel() { + public void removeAllListeners() { if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { - listener.onAnimationCancel(this); - } + mListeners.clear(); + mListeners = null; } - // Just set the CANCELED flag - this causes the animation to end the next time a frame - // is processed. - mPlayingState = CANCELED; } @Override - public void end() { - if (!sAnimations.contains(this) && !sPendingAnimations.contains(this)) { - // Special case if the animation has not yet started; get it ready for ending - mStartedDelay = false; - sPendingAnimations.add(this); - if (sAnimationHandler == null) { - sAnimationHandler = new AnimationHandler(); + public Animator clone() { + try { + final Animator anim = (Animator) super.clone(); + if (mListeners != null) { + ArrayList<AnimatorListener> oldListeners = mListeners; + anim.mListeners = new ArrayList<AnimatorListener>(); + int numListeners = oldListeners.size(); + for (int i = 0; i < numListeners; ++i) { + anim.mListeners.add(oldListeners.get(i)); + } } - sAnimationHandler.sendEmptyMessage(ANIMATION_START); + return anim; + } catch (CloneNotSupportedException e) { + throw new AssertionError(); } - // Just set the ENDED flag - this causes the animation to end the next time a frame - // is processed. - mPlayingState = ENDED; - } - - @Override - public boolean isRunning() { - // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet - return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED); } /** - * Plays the Animator in reverse. If the animation is already running, - * it will stop itself and play backwards from the point reached when reverse was called. - * If the animation is not currently running, then it will start from the end and - * play backwards. This behavior is only set for the current animation; future playing - * of the animation will use the default behavior of playing forward. + * This method tells the object to use appropriate information to extract + * starting values for the animation. For example, a AnimatorSet object will pass + * this call to its child objects to tell them to set up the values. A + * ObjectAnimator object will use the information it has about its target object + * and PropertyValuesHolder objects to get the start values for its properties. + * An ValueAnimator object will ignore the request since it does not have enough + * information (such as a target object) to gather these values. */ - public void reverse() { - mPlayingBackwards = !mPlayingBackwards; - if (mPlayingState == RUNNING) { - long currentTime = AnimationUtils.currentAnimationTimeMillis(); - long currentPlayTime = currentTime - mStartTime; - long timeLeft = mDuration - currentPlayTime; - mStartTime = currentTime - timeLeft; - } else { - start(true); - } + public void setupStartValues() { } /** - * Called internally to end an animation by removing it from the animations list. Must be - * called on the UI thread. + * This method tells the object to use appropriate information to extract + * ending values for the animation. For example, a AnimatorSet object will pass + * this call to its child objects to tell them to set up the values. A + * ObjectAnimator object will use the information it has about its target object + * and PropertyValuesHolder objects to get the start values for its properties. + * An ValueAnimator object will ignore the request since it does not have enough + * information (such as a target object) to gather these values. */ - private void endAnimation() { - sAnimations.remove(this); - mPlayingState = STOPPED; - if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { - listener.onAnimationEnd(this); - } - } + public void setupEndValues() { } /** - * Called internally to start an animation by adding it to the active animations list. Must be - * called on the UI thread. - */ - private void startAnimation() { - initAnimation(); - sAnimations.add(this); - if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { - listener.onAnimationStart(this); - } - } - } - - /** - * Internal function called to process an animation frame on an animation that is currently - * sleeping through its <code>startDelay</code> phase. The return value indicates whether it - * should be woken up and put on the active animations queue. + * Sets the target object whose property will be animated by this animation. Not all subclasses + * operate on target objects (for example, {@link ValueAnimator}, but this method + * is on the superclass for the convenience of dealing generically with those subclasses + * that do handle targets. * - * @param currentTime The current animation time, used to calculate whether the animation - * has exceeded its <code>startDelay</code> and should be started. - * @return True if the animation's <code>startDelay</code> has been exceeded and the animation - * should be added to the set of active animations. + * @param target The object being animated */ - private boolean delayedAnimationFrame(long currentTime) { - if (mPlayingState == CANCELED || mPlayingState == ENDED) { - // end the delay, process an animation frame to actually cancel it - return true; - } - if (!mStartedDelay) { - mStartedDelay = true; - mDelayStartTime = currentTime; - } else { - long deltaTime = currentTime - mDelayStartTime; - if (deltaTime > mStartDelay) { - // startDelay ended - start the anim and record the - // mStartTime appropriately - mStartTime = currentTime - (deltaTime - mStartDelay); - mPlayingState = RUNNING; - return true; - } - } - return false; + public void setTarget(Object target) { } /** - * This internal function processes a single animation frame for a given animation. The - * currentTime parameter is the timing pulse sent by the handler, used to calculate the - * elapsed duration, and therefore - * the elapsed fraction, of the animation. The return value indicates whether the animation - * should be ended (which happens when the elapsed time of the animation exceeds the - * animation's duration, including the repeatCount). - * - * @param currentTime The current time, as tracked by the static timing handler - * @return true if the animation's duration, including any repetitions due to - * <code>repeatCount</code> has been exceeded and the animation should be ended. + * <p>An animation listener receives notifications from an animation. + * Notifications indicate animation related events, such as the end or the + * repetition of the animation.</p> */ - private boolean animationFrame(long currentTime) { - boolean done = false; - - if (mPlayingState == STOPPED) { - mPlayingState = RUNNING; - if (mSeekTime < 0) { - mStartTime = currentTime; - } else { - mStartTime = currentTime - mSeekTime; - // Now that we're playing, reset the seek time - mSeekTime = -1; - } - } - switch (mPlayingState) { - case RUNNING: - case SEEKED: - float fraction = (float)(currentTime - mStartTime) / mDuration; - if (fraction >= 1f) { - if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { - // Time to repeat - if (mListeners != null) { - for (AnimatableListener listener : mListeners) { - listener.onAnimationRepeat(this); - } - } - ++mCurrentIteration; - if (mRepeatMode == REVERSE) { - mPlayingBackwards = mPlayingBackwards ? false : true; - } - // TODO: doesn't account for fraction going Wayyyyy over 1, like 2+ - fraction = fraction - 1f; - mStartTime += mDuration; - } else { - done = true; - fraction = Math.min(fraction, 1.0f); - } - } - if (mPlayingBackwards) { - fraction = 1f - fraction; - } - animateValue(fraction); - break; - case ENDED: - // The final value set on the target varies, depending on whether the animation - // was supposed to repeat an odd number of times - if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) { - animateValue(0f); - } else { - animateValue(1f); - } - // Fall through to set done flag - case CANCELED: - done = true; - mPlayingState = STOPPED; - break; - } - - return done; - } + public static interface AnimatorListener { + /** + * <p>Notifies the start of the animation.</p> + * + * @param animation The started animation. + */ + void onAnimationStart(Animator animation); - /** - * This method is called with the elapsed fraction of the animation during every - * animation frame. This function turns the elapsed fraction into an interpolated fraction - * and then into an animated value (from the evaluator. The function is called mostly during - * animation updates, but it is also called when the <code>end()</code> - * function is called, to set the final value on the property. - * - * <p>Overrides of this method must call the superclass to perform the calculation - * of the animated value.</p> - * - * @param fraction The elapsed fraction of the animation. - */ - void animateValue(float fraction) { - fraction = mInterpolator.getInterpolation(fraction); - int numValues = mValues.length; - for (int i = 0; i < numValues; ++i) { - mValues[i].calculateValue(fraction); - } - if (mUpdateListeners != null) { - int numListeners = mUpdateListeners.size(); - for (int i = 0; i < numListeners; ++i) { - mUpdateListeners.get(i).onAnimationUpdate(this); - } - } - } + /** + * <p>Notifies the end of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.</p> + * + * @param animation The animation which reached its end. + */ + void onAnimationEnd(Animator animation); - @Override - public Animator clone() { - final Animator anim = (Animator) super.clone(); - if (mUpdateListeners != null) { - ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners; - anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); - int numListeners = oldListeners.size(); - for (int i = 0; i < numListeners; ++i) { - anim.mUpdateListeners.add(oldListeners.get(i)); - } - } - anim.mSeekTime = -1; - anim.mPlayingBackwards = false; - anim.mCurrentIteration = 0; - anim.mInitialized = false; - anim.mPlayingState = STOPPED; - anim.mStartedDelay = false; - PropertyValuesHolder[] oldValues = mValues; - if (oldValues != null) { - int numValues = oldValues.length; - anim.mValues = new PropertyValuesHolder[numValues]; - for (int i = 0; i < numValues; ++i) { - anim.mValues[i] = oldValues[i].clone(); - } - anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); - for (int i = 0; i < numValues; ++i) { - PropertyValuesHolder valuesHolder = mValues[i]; - anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); - } - } - return anim; - } + /** + * <p>Notifies the cancellation of the animation. This callback is not invoked + * for animations with repeat count set to INFINITE.</p> + * + * @param animation The animation which was canceled. + */ + void onAnimationCancel(Animator animation); - /** - * Implementors of this interface can add themselves as update listeners - * to an <code>Animator</code> instance to receive callbacks on every animation - * frame, after the current frame's values have been calculated for that - * <code>Animator</code>. - */ - public static interface AnimatorUpdateListener { /** - * <p>Notifies the occurrence of another frame of the animation.</p> + * <p>Notifies the repetition of the animation.</p> * * @param animation The animation which was repeated. */ - void onAnimationUpdate(Animator animation); - + void onAnimationRepeat(Animator animation); } -}
\ No newline at end of file +} diff --git a/core/java/android/animation/AnimatableInflater.java b/core/java/android/animation/AnimatorInflater.java index 88fa77e..0016459 100644 --- a/core/java/android/animation/AnimatableInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -30,7 +30,7 @@ import java.io.IOException; import java.util.ArrayList; /** - * This class is used to instantiate menu XML files into Animatable objects. + * This class is used to instantiate menu XML files into Animator objects. * <p> * For performance reasons, menu inflation relies heavily on pre-processing of * XML files that is done at build time. Therefore, it is not currently possible @@ -38,10 +38,10 @@ import java.util.ArrayList; * it only works with an XmlPullParser returned from a compiled resource (R. * <em>something</em> file.) */ -public class AnimatableInflater { +public class AnimatorInflater { /** - * These flags are used when parsing Sequencer objects + * These flags are used when parsing AnimatorSet objects */ private static final int TOGETHER = 0; private static final int SEQUENTIALLY = 1; @@ -56,20 +56,20 @@ public class AnimatableInflater { private static final int VALUE_TYPE_CUSTOM = 4; /** - * Loads an {@link Animatable} object from a resource + * Loads an {@link Animator} object from a resource * * @param context Application context used to access resources * @param id The resource id of the animation to load - * @return The animatable object reference by the specified id + * @return The animator object reference by the specified id * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded */ - public static Animatable loadAnimatable(Context context, int id) + public static Animator loadAnimator(Context context, int id) throws NotFoundException { XmlResourceParser parser = null; try { parser = context.getResources().getAnimation(id); - return createAnimatableFromXml(context, parser); + return createAnimatorFromXml(context, parser); } catch (XmlPullParserException ex) { Resources.NotFoundException rnf = new Resources.NotFoundException("Can't load animation resource ID #0x" + @@ -87,18 +87,18 @@ public class AnimatableInflater { } } - private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser) + private static Animator createAnimatorFromXml(Context c, XmlPullParser parser) throws XmlPullParserException, IOException { - return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0); + return createAnimatorFromXml(c, parser, Xml.asAttributeSet(parser), null, 0); } - private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser, - AttributeSet attrs, Sequencer parent, int sequenceOrdering) + private static Animator createAnimatorFromXml(Context c, XmlPullParser parser, + AttributeSet attrs, AnimatorSet parent, int sequenceOrdering) throws XmlPullParserException, IOException { - Animatable anim = null; - ArrayList<Animatable> childAnims = null; + Animator anim = null; + ArrayList<Animator> childAnims = null; // Make sure we are on a start tag. int type; @@ -113,17 +113,17 @@ public class AnimatableInflater { String name = parser.getName(); - if (name.equals("property")) { - anim = loadPropertyAnimator(c, attrs); + if (name.equals("objectAnimator")) { + anim = loadObjectAnimator(c, attrs); } else if (name.equals("animator")) { anim = loadAnimator(c, attrs, null); - } else if (name.equals("sequencer")) { - anim = new Sequencer(); + } else if (name.equals("set")) { + anim = new AnimatorSet(); TypedArray a = c.obtainStyledAttributes(attrs, - com.android.internal.R.styleable.Sequencer); - int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering, + com.android.internal.R.styleable.AnimatorSet); + int ordering = a.getInt(com.android.internal.R.styleable.AnimatorSet_ordering, TOGETHER); - createAnimatableFromXml(c, parser, attrs, (Sequencer) anim, ordering); + createAnimatorFromXml(c, parser, attrs, (AnimatorSet) anim, ordering); a.recycle(); } else { throw new RuntimeException("Unknown animator name: " + parser.getName()); @@ -131,15 +131,15 @@ public class AnimatableInflater { if (parent != null) { if (childAnims == null) { - childAnims = new ArrayList<Animatable>(); + childAnims = new ArrayList<Animator>(); } childAnims.add(anim); } } if (parent != null && childAnims != null) { - Animatable[] animsArray = new Animatable[childAnims.size()]; + Animator[] animsArray = new Animator[childAnims.size()]; int index = 0; - for (Animatable a : childAnims) { + for (Animator a : childAnims) { animsArray[index++] = a; } if (sequenceOrdering == TOGETHER) { @@ -153,10 +153,10 @@ public class AnimatableInflater { } - private static PropertyAnimator loadPropertyAnimator(Context context, AttributeSet attrs) + private static ObjectAnimator loadObjectAnimator(Context context, AttributeSet attrs) throws NotFoundException { - PropertyAnimator anim = new PropertyAnimator(); + ObjectAnimator anim = new ObjectAnimator(); loadAnimator(context, attrs, anim); @@ -179,7 +179,7 @@ public class AnimatableInflater { * @param context the application environment * @param attrs the set of attributes holding the animation parameters */ - private static Animator loadAnimator(Context context, AttributeSet attrs, Animator anim) + private static ValueAnimator loadAnimator(Context context, AttributeSet attrs, ValueAnimator anim) throws NotFoundException { TypedArray a = @@ -236,7 +236,7 @@ public class AnimatableInflater { } if (anim == null) { - anim = new Animator(duration, valueFrom, valueTo); + anim = new ValueAnimator(duration, valueFrom, valueTo); } else { anim.setDuration(duration); anim.setValues(valueFrom, valueTo); @@ -251,7 +251,7 @@ public class AnimatableInflater { if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) { anim.setRepeatMode( a.getInt(com.android.internal.R.styleable.Animator_repeatMode, - Animator.RESTART)); + ValueAnimator.RESTART)); } if (evaluator != null) { anim.setEvaluator(evaluator); diff --git a/core/java/android/animation/AnimatableListenerAdapter.java b/core/java/android/animation/AnimatorListenerAdapter.java index c169b28..6182389 100644 --- a/core/java/android/animation/AnimatableListenerAdapter.java +++ b/core/java/android/animation/AnimatorListenerAdapter.java @@ -16,41 +16,39 @@ package android.animation; -import android.animation.Animatable.AnimatableListener; - /** - * This adapter class provides empty implementations of the methods from {@link AnimatableListener}. + * This adapter class provides empty implementations of the methods from {@link android.animation.Animator.AnimatorListener}. * Any custom listener that cares only about a subset of the methods of this listener can * simply subclass this adapter class instead of implementing the interface directly. */ -public abstract class AnimatableListenerAdapter implements AnimatableListener { +public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener { /** * {@inheritdoc} */ @Override - public void onAnimationCancel(Animatable animation) { + public void onAnimationCancel(Animator animation) { } /** * {@inheritdoc} */ @Override - public void onAnimationEnd(Animatable animation) { + public void onAnimationEnd(Animator animation) { } /** * {@inheritdoc} */ @Override - public void onAnimationRepeat(Animatable animation) { + public void onAnimationRepeat(Animator animation) { } /** * {@inheritdoc} */ @Override - public void onAnimationStart(Animatable animation) { + public void onAnimationStart(Animator animation) { } } diff --git a/core/java/android/animation/Sequencer.java b/core/java/android/animation/AnimatorSet.java index 04bede0..a8385e4 100644 --- a/core/java/android/animation/Sequencer.java +++ b/core/java/android/animation/AnimatorSet.java @@ -16,35 +16,31 @@ package android.animation; -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import java.util.ArrayList; import java.util.HashMap; /** - * This class plays a set of {@link Animatable} objects in the specified order. Animations + * This class plays a set of {@link Animator} objects in the specified order. Animations * can be set up to play together, in sequence, or after a specified delay. * - * <p>There are two different approaches to adding animations to a <code>Sequencer</code>: - * either the {@link Sequencer#playTogether(Animatable[]) playTogether()} or - * {@link Sequencer#playSequentially(Animatable[]) playSequentially()} methods can be called to add - * a set of animations all at once, or the {@link Sequencer#play(Animatable)} can be - * used in conjunction with methods in the {@link android.animation.Sequencer.Builder Builder} + * <p>There are two different approaches to adding animations to a <code>AnimatorSet</code>: + * either the {@link AnimatorSet#playTogether(Animator[]) playTogether()} or + * {@link AnimatorSet#playSequentially(Animator[]) playSequentially()} methods can be called to add + * a set of animations all at once, or the {@link AnimatorSet#play(Animator)} can be + * used in conjunction with methods in the {@link AnimatorSet.Builder Builder} * class to add animations * one by one.</p> * - * <p>It is possible to set up a <code>Sequencer</code> with circular dependencies between + * <p>It is possible to set up a <code>AnimatorSet</code> with circular dependencies between * its animations. For example, an animation a1 could be set up to start before animation a2, a2 * before a3, and a3 before a1. The results of this configuration are undefined, but will typically * result in none of the affected animations being played. Because of this (and because * circular dependencies do not make logical sense anyway), circular dependencies * should be avoided, and the dependency flow of animations should only be in one direction. */ -public final class Sequencer extends Animatable { +public final class AnimatorSet extends Animator { /** * Internal variables @@ -55,21 +51,21 @@ public final class Sequencer extends Animatable { /** * Tracks animations currently being played, so that we know what to - * cancel or end when cancel() or end() is called on this Sequencer + * cancel or end when cancel() or end() is called on this AnimatorSet */ - private ArrayList<Animatable> mPlayingSet = new ArrayList<Animatable>(); + private ArrayList<Animator> mPlayingSet = new ArrayList<Animator>(); /** - * Contains all nodes, mapped to their respective Animatables. When new - * dependency information is added for an Animatable, we want to add it - * to a single node representing that Animatable, not create a new Node + * Contains all nodes, mapped to their respective Animators. When new + * dependency information is added for an Animator, we want to add it + * to a single node representing that Animator, not create a new Node * if one already exists. */ - private HashMap<Animatable, Node> mNodeMap = new HashMap<Animatable, Node>(); + private HashMap<Animator, Node> mNodeMap = new HashMap<Animator, Node>(); /** - * Set of all nodes created for this Sequencer. This list is used upon - * starting the sequencer, and the nodes are placed in sorted order into the + * Set of all nodes created for this AnimatorSet. This list is used upon + * starting the set, and the nodes are placed in sorted order into the * sortedNodes collection. */ private ArrayList<Node> mNodes = new ArrayList<Node>(); @@ -88,12 +84,12 @@ public final class Sequencer extends Animatable { */ private boolean mNeedsSort = true; - private SequencerAnimatableListener mSequenceListener = null; + private AnimatorSetListener mSetListener = null; /** - * Flag indicating that the Sequencer has been canceled (by calling cancel() or end()). + * Flag indicating that the AnimatorSet has been canceled (by calling cancel() or end()). * This flag is used to avoid starting other animations when currently-playing - * child animations of this Sequencer end. + * child animations of this AnimatorSet end. */ boolean mCanceled = false; @@ -102,55 +98,55 @@ public final class Sequencer extends Animatable { // How long the child animations should last in ms. The default value is negative, which - // simply means that there is no duration set on the Sequencer. When a real duration is + // simply means that there is no duration set on the AnimatorSet. When a real duration is // set, it is passed along to the child animations. private long mDuration = -1; /** - * Sets up this Sequencer to play all of the supplied animations at the same time. + * Sets up this AnimatorSet to play all of the supplied animations at the same time. * - * @param sequenceItems The animations that will be started simultaneously. + * @param items The animations that will be started simultaneously. */ - public void playTogether(Animatable... sequenceItems) { - if (sequenceItems != null) { + public void playTogether(Animator... items) { + if (items != null) { mNeedsSort = true; - Builder builder = play(sequenceItems[0]); - for (int i = 1; i < sequenceItems.length; ++i) { - builder.with(sequenceItems[i]); + Builder builder = play(items[0]); + for (int i = 1; i < items.length; ++i) { + builder.with(items[i]); } } } /** - * Sets up this Sequencer to play each of the supplied animations when the + * Sets up this AnimatorSet to play each of the supplied animations when the * previous animation ends. * - * @param sequenceItems The aniamtions that will be started one after another. + * @param items The aniamtions that will be started one after another. */ - public void playSequentially(Animatable... sequenceItems) { - if (sequenceItems != null) { + public void playSequentially(Animator... items) { + if (items != null) { mNeedsSort = true; - if (sequenceItems.length == 1) { - play(sequenceItems[0]); + if (items.length == 1) { + play(items[0]); } else { - for (int i = 0; i < sequenceItems.length - 1; ++i) { - play(sequenceItems[i]).before(sequenceItems[i+1]); + for (int i = 0; i < items.length - 1; ++i) { + play(items[i]).before(items[i+1]); } } } } /** - * Returns the current list of child Animatable objects controlled by this - * Sequencer. This is a copy of the internal list; modifications to the returned list - * will not affect the Sequencer, although changes to the underlying Animatable objects - * will affect those objects being managed by the Sequencer. + * Returns the current list of child Animator objects controlled by this + * AnimatorSet. This is a copy of the internal list; modifications to the returned list + * will not affect the AnimatorSet, although changes to the underlying Animator objects + * will affect those objects being managed by the AnimatorSet. * - * @return ArrayList<Animatable> The list of child animations of this Sequencer. + * @return ArrayList<Animator> The list of child animations of this AnimatorSet. */ - public ArrayList<Animatable> getChildAnimations() { - ArrayList<Animatable> childList = new ArrayList<Animatable>(); + public ArrayList<Animator> getChildAnimations() { + ArrayList<Animator> childList = new ArrayList<Animator>(); for (Node node : mNodes) { childList.add(node.animation); } @@ -159,28 +155,28 @@ public final class Sequencer extends Animatable { /** * Sets the target object for all current {@link #getChildAnimations() child animations} - * of this Sequencer that take targets ({@link android.animation.PropertyAnimator} and - * Sequencer). + * of this AnimatorSet that take targets ({@link ObjectAnimator} and + * AnimatorSet). * * @param target The object being animated */ @Override public void setTarget(Object target) { for (Node node : mNodes) { - Animatable animation = node.animation; - if (animation instanceof Sequencer) { - ((Sequencer)animation).setTarget(target); - } else if (animation instanceof PropertyAnimator) { - ((PropertyAnimator)animation).setTarget(target); + Animator animation = node.animation; + if (animation instanceof AnimatorSet) { + ((AnimatorSet)animation).setTarget(target); + } else if (animation instanceof ObjectAnimator) { + ((ObjectAnimator)animation).setTarget(target); } } } /** * Sets the Interpolator for all current {@link #getChildAnimations() child animations} - * of this Sequencer. + * of this AnimatorSet. * - * @param interpolator the interpolator to be used by each child animation of this Sequencer + * @param interpolator the interpolator to be used by each child animation of this AnimatorSet */ @Override public void setInterpolator(Interpolator interpolator) { @@ -194,11 +190,11 @@ public final class Sequencer extends Animatable { * set up playing constraints. This initial <code>play()</code> method * tells the <code>Builder</code> the animation that is the dependency for * the succeeding commands to the <code>Builder</code>. For example, - * calling <code>play(a1).with(a2)</code> sets up the Sequence to play + * calling <code>play(a1).with(a2)</code> sets up the AnimatorSet to play * <code>a1</code> and <code>a2</code> at the same time, - * <code>play(a1).before(a2)</code> sets up the Sequence to play + * <code>play(a1).before(a2)</code> sets up the AnimatorSet to play * <code>a1</code> first, followed by <code>a2</code>, and - * <code>play(a1).after(a2)</code> sets up the Sequence to play + * <code>play(a1).after(a2)</code> sets up the AnimatorSet to play * <code>a2</code> first, followed by <code>a1</code>. * * <p>Note that <code>play()</code> is the only way to tell the @@ -213,11 +209,11 @@ public final class Sequencer extends Animatable { * @param anim The animation that is the dependency used in later calls to the * methods in the returned <code>Builder</code> object. A null parameter will result * in a null <code>Builder</code> return value. - * @return Builder The object that constructs the sequence based on the dependencies + * @return Builder The object that constructs the AnimatorSet based on the dependencies * outlined in the calls to <code>play</code> and the other methods in the * <code>Builder</code object. */ - public Builder play(Animatable anim) { + public Builder play(Animator anim) { if (anim != null) { mNeedsSort = true; return new Builder(anim); @@ -228,7 +224,7 @@ public final class Sequencer extends Animatable { /** * {@inheritDoc} * - * <p>Note that canceling a <code>Sequencer</code> also cancels all of the animations that it is + * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it is * responsible for.</p> */ @SuppressWarnings("unchecked") @@ -236,9 +232,9 @@ public final class Sequencer extends Animatable { public void cancel() { mCanceled = true; if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { listener.onAnimationCancel(this); } } @@ -252,7 +248,7 @@ public final class Sequencer extends Animatable { /** * {@inheritDoc} * - * <p>Note that ending a <code>Sequencer</code> also ends all of the animations that it is + * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is * responsible for.</p> */ @Override @@ -262,10 +258,10 @@ public final class Sequencer extends Animatable { // hasn't been started yet - sort the nodes now, then end them sortNodes(); for (Node node : mSortedNodes) { - if (mSequenceListener == null) { - mSequenceListener = new SequencerAnimatableListener(this); + if (mSetListener == null) { + mSetListener = new AnimatorSetListener(this); } - node.animation.addListener(mSequenceListener); + node.animation.addListener(mSetListener); } } if (mSortedNodes.size() > 0) { @@ -276,9 +272,9 @@ public final class Sequencer extends Animatable { } /** - * Returns true if any of the child animations of this Sequencer have been started and have not + * Returns true if any of the child animations of this AnimatorSet have been started and have not * yet ended. - * @return Whether this Sequencer has been started and has not yet ended. + * @return Whether this AnimatorSet has been started and has not yet ended. */ @Override public boolean isRunning() { @@ -313,12 +309,12 @@ public final class Sequencer extends Animatable { } /** - * Gets the length of each of the child animations of this Sequencer. This value may - * be less than 0, which indicates that no duration has been set on this Sequencer + * Gets the length of each of the child animations of this AnimatorSet. This value may + * be less than 0, which indicates that no duration has been set on this AnimatorSet * and each of the child animations will use their own duration. * * @return The length of the animation, in milliseconds, of each of the child - * animations of this Sequencer. + * animations of this AnimatorSet. */ @Override public long getDuration() { @@ -326,12 +322,12 @@ public final class Sequencer extends Animatable { } /** - * Sets the length of each of the current child animations of this Sequencer. By default, - * each child animation will use its own duration. If the duration is set on the Sequencer, + * Sets the length of each of the current child animations of this AnimatorSet. By default, + * each child animation will use its own duration. If the duration is set on the AnimatorSet, * then each child animation inherits this duration. * * @param duration The length of the animation, in milliseconds, of each of the child - * animations of this Sequencer. + * animations of this AnimatorSet. */ @Override public void setDuration(long duration) { @@ -339,7 +335,7 @@ public final class Sequencer extends Animatable { throw new IllegalArgumentException("duration must be a value of zero or greater"); } for (Node node : mNodes) { - // TODO: don't set the duration of the timing-only nodes created by Sequencer to + // TODO: don't set the duration of the timing-only nodes created by AnimatorSet to // insert "play-after" delays node.animation.setDuration(duration); } @@ -349,7 +345,7 @@ public final class Sequencer extends Animatable { /** * {@inheritDoc} * - * <p>Starting this <code>Sequencer</code> will, in turn, start the animations for which + * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which * it is responsible. The details of when exactly those animations are started depends on * the dependency relationships that have been set up between the animations. */ @@ -368,8 +364,8 @@ public final class Sequencer extends Animatable { // when some other animation also wants to start when the first animation begins. final ArrayList<Node> nodesToStart = new ArrayList<Node>(); for (Node node : mSortedNodes) { - if (mSequenceListener == null) { - mSequenceListener = new SequencerAnimatableListener(this); + if (mSetListener == null) { + mSetListener = new AnimatorSetListener(this); } if (node.dependencies == null || node.dependencies.size() == 0) { nodesToStart.add(node); @@ -380,7 +376,7 @@ public final class Sequencer extends Animatable { } node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone(); } - node.animation.addListener(mSequenceListener); + node.animation.addListener(mSetListener); } // Now that all dependencies are set up, start the animations that should be started. if (mStartDelay <= 0) { @@ -390,9 +386,9 @@ public final class Sequencer extends Animatable { } } else { // TODO: Need to cancel out of the delay appropriately - Animator delayAnim = new Animator(mStartDelay, 0f, 1f); - delayAnim.addListener(new AnimatableListenerAdapter() { - public void onAnimationEnd(Animatable anim) { + ValueAnimator delayAnim = new ValueAnimator(mStartDelay, 0f, 1f); + delayAnim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator anim) { for (Node node : nodesToStart) { node.animation.start(); mPlayingSet.add(node.animation); @@ -401,20 +397,20 @@ public final class Sequencer extends Animatable { }); } if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { listener.onAnimationStart(this); } } } @Override - public Sequencer clone() { - final Sequencer anim = (Sequencer) super.clone(); + public AnimatorSet clone() { + final AnimatorSet anim = (AnimatorSet) super.clone(); /* * The basic clone() operation copies all items. This doesn't work very well for - * Sequencer, because it will copy references that need to be recreated and state + * AnimatorSet, because it will copy references that need to be recreated and state * that may not apply. What we need to do now is put the clone in an uninitialized * state, with fresh, empty data structures. Then we will build up the nodes list * manually, as we clone each Node (and its animation). The clone will then be sorted, @@ -422,13 +418,13 @@ public final class Sequencer extends Animatable { */ anim.mNeedsSort = true; anim.mCanceled = false; - anim.mPlayingSet = new ArrayList<Animatable>(); - anim.mNodeMap = new HashMap<Animatable, Node>(); + anim.mPlayingSet = new ArrayList<Animator>(); + anim.mNodeMap = new HashMap<Animator, Node>(); anim.mNodes = new ArrayList<Node>(); anim.mSortedNodes = new ArrayList<Node>(); // Walk through the old nodes list, cloning each node and adding it to the new nodemap. - // One problem is that the old node dependencies point to nodes in the old sequencer. + // One problem is that the old node dependencies point to nodes in the old AnimatorSet. // We need to track the old/new nodes in order to reconstruct the dependencies in the clone. HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new> for (Node node : mNodes) { @@ -441,21 +437,21 @@ public final class Sequencer extends Animatable { nodeClone.tmpDependencies = null; nodeClone.nodeDependents = null; nodeClone.nodeDependencies = null; - // clear out any listeners that were set up by the sequencer; these will + // clear out any listeners that were set up by the AnimatorSet; these will // be set up when the clone's nodes are sorted - ArrayList<AnimatableListener> cloneListeners = nodeClone.animation.getListeners(); + ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners(); if (cloneListeners != null) { - ArrayList<AnimatableListener> listenersToRemove = null; - for (AnimatableListener listener : cloneListeners) { - if (listener instanceof SequencerAnimatableListener) { + ArrayList<AnimatorListener> listenersToRemove = null; + for (AnimatorListener listener : cloneListeners) { + if (listener instanceof AnimatorSetListener) { if (listenersToRemove == null) { - listenersToRemove = new ArrayList<AnimatableListener>(); + listenersToRemove = new ArrayList<AnimatorListener>(); } listenersToRemove.add(listener); } } if (listenersToRemove != null) { - for (AnimatableListener listener : listenersToRemove) { + for (AnimatorListener listener : listenersToRemove) { cloneListeners.remove(listener); } } @@ -483,9 +479,9 @@ public final class Sequencer extends Animatable { * animations. If an animation has multiple dependencies on other animations, then * all dependencies must be satisfied before the animation is started. */ - private static class DependencyListener implements AnimatableListener { + private static class DependencyListener implements AnimatorListener { - private Sequencer mSequencer; + private AnimatorSet mAnimatorSet; // The node upon which the dependency is based. private Node mNode; @@ -494,8 +490,8 @@ public final class Sequencer extends Animatable { // the node private int mRule; - public DependencyListener(Sequencer sequencer, Node node, int rule) { - this.mSequencer = sequencer; + public DependencyListener(AnimatorSet animatorSet, Node node, int rule) { + this.mAnimatorSet = animatorSet; this.mNode = node; this.mRule = rule; } @@ -505,13 +501,13 @@ public final class Sequencer extends Animatable { * to prevent follow-on animations from running when some dependency * animation is canceled. */ - public void onAnimationCancel(Animatable animation) { + public void onAnimationCancel(Animator animation) { } /** * An end event is received - see if this is an event we are listening for */ - public void onAnimationEnd(Animatable animation) { + public void onAnimationEnd(Animator animation) { if (mRule == Dependency.AFTER) { startIfReady(animation); } @@ -520,13 +516,13 @@ public final class Sequencer extends Animatable { /** * Ignore repeat events for now */ - public void onAnimationRepeat(Animatable animation) { + public void onAnimationRepeat(Animator animation) { } /** * A start event is received - see if this is an event we are listening for */ - public void onAnimationStart(Animatable animation) { + public void onAnimationStart(Animator animation) { if (mRule == Dependency.WITH) { startIfReady(animation); } @@ -538,9 +534,9 @@ public final class Sequencer extends Animatable { * the animation. * @param dependencyAnimation the animation that sent the event. */ - private void startIfReady(Animatable dependencyAnimation) { - if (mSequencer.mCanceled) { - // if the parent Sequencer was canceled, then don't start any dependent anims + private void startIfReady(Animator dependencyAnimation) { + if (mAnimatorSet.mCanceled) { + // if the parent AnimatorSet was canceled, then don't start any dependent anims return; } Dependency dependencyToRemove = null; @@ -558,37 +554,37 @@ public final class Sequencer extends Animatable { if (mNode.tmpDependencies.size() == 0) { // all dependencies satisfied: start the animation mNode.animation.start(); - mSequencer.mPlayingSet.add(mNode.animation); + mAnimatorSet.mPlayingSet.add(mNode.animation); } } } - private class SequencerAnimatableListener implements AnimatableListener { + private class AnimatorSetListener implements AnimatorListener { - private Sequencer mSequencer; + private AnimatorSet mAnimatorSet; - SequencerAnimatableListener(Sequencer sequencer) { - mSequencer = sequencer; + AnimatorSetListener(AnimatorSet animatorSet) { + mAnimatorSet = animatorSet; } - public void onAnimationCancel(Animatable animation) { + public void onAnimationCancel(Animator animation) { if (mPlayingSet.size() == 0) { if (mListeners != null) { - for (AnimatableListener listener : mListeners) { - listener.onAnimationCancel(mSequencer); + for (AnimatorListener listener : mListeners) { + listener.onAnimationCancel(mAnimatorSet); } } } } @SuppressWarnings("unchecked") - public void onAnimationEnd(Animatable animation) { + public void onAnimationEnd(Animator animation) { animation.removeListener(this); mPlayingSet.remove(animation); - Node animNode = mSequencer.mNodeMap.get(animation); + Node animNode = mAnimatorSet.mNodeMap.get(animation); animNode.done = true; - ArrayList<Node> sortedNodes = mSequencer.mSortedNodes; + ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes; boolean allDone = true; for (Node node : sortedNodes) { if (!node.done) { @@ -598,23 +594,23 @@ public final class Sequencer extends Animatable { } if (allDone) { // If this was the last child animation to end, then notify listeners that this - // sequencer has ended + // AnimatorSet has ended if (mListeners != null) { - ArrayList<AnimatableListener> tmpListeners = - (ArrayList<AnimatableListener>) mListeners.clone(); - for (AnimatableListener listener : tmpListeners) { - listener.onAnimationEnd(mSequencer); + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationEnd(mAnimatorSet); } } } } // Nothing to do - public void onAnimationRepeat(Animatable animation) { + public void onAnimationRepeat(Animator animation) { } // Nothing to do - public void onAnimationStart(Animatable animation) { + public void onAnimationStart(Animator animation) { } } @@ -658,7 +654,7 @@ public final class Sequencer extends Animatable { mNeedsSort = false; if (mSortedNodes.size() != mNodes.size()) { throw new IllegalStateException("Circular dependencies cannot exist" - + " in Sequencer"); + + " in AnimatorSet"); } } else { // Doesn't need sorting, but still need to add in the nodeDependencies list @@ -702,13 +698,13 @@ public final class Sequencer extends Animatable { } /** - * A Node is an embodiment of both the Animatable that it wraps as well as + * A Node is an embodiment of both the Animator that it wraps as well as * any dependencies that are associated with that Animation. This includes * both dependencies upon other nodes (in the dependencies list) as * well as dependencies of other nodes upon this (in the nodeDependents list). */ private static class Node implements Cloneable { - public Animatable animation; + public Animator animation; /** * These are the dependencies that this node's animation has on other @@ -723,8 +719,8 @@ public final class Sequencer extends Animatable { * But we also use the list to keep track of when multiple dependencies are satisfied, * but removing each dependency as it is satisfied. We do not want to remove * the dependency itself from the list, because we need to retain that information - * if the sequencer is launched in the future. So we create a copy of the dependency - * list when the sequencer starts and use this tmpDependencies list to track the + * if the AnimatorSet is launched in the future. So we create a copy of the dependency + * list when the AnimatorSet starts and use this tmpDependencies list to track the * list of satisfied dependencies. */ public ArrayList<Dependency> tmpDependencies = null; @@ -744,8 +740,8 @@ public final class Sequencer extends Animatable { /** * Flag indicating whether the animation in this node is finished. This flag - * is used by Sequencer to check, as each animation ends, whether all child animations - * are done and it's time to send out an end event for the entire Sequencer. + * is used by AnimatorSet to check, as each animation ends, whether all child animations + * are done and it's time to send out an end event for the entire AnimatorSet. */ public boolean done = false; @@ -756,7 +752,7 @@ public final class Sequencer extends Animatable { * * @param animation The animation that the Node encapsulates. */ - public Node(Animatable animation) { + public Node(Animator animation) { this.animation = animation; } @@ -785,7 +781,7 @@ public final class Sequencer extends Animatable { public Node clone() { try { Node node = (Node) super.clone(); - node.animation = (Animatable) animation.clone(); + node.animation = (Animator) animation.clone(); return node; } catch (CloneNotSupportedException e) { throw new AssertionError(); @@ -795,45 +791,45 @@ public final class Sequencer extends Animatable { /** * The <code>Builder</code> object is a utility class to facilitate adding animations to a - * <code>Sequencer</code> along with the relationships between the various animations. The + * <code>AnimatorSet</code> along with the relationships between the various animations. The * intention of the <code>Builder</code> methods, along with the {@link - * Sequencer#play(Animatable) play()} method of <code>Sequencer</code> is to make it possible to + * AnimatorSet#play(Animator) play()} method of <code>AnimatorSet</code> is to make it possible to * express the dependency relationships of animations in a natural way. Developers can also use - * the {@link Sequencer#playTogether(Animatable[]) playTogether()} and {@link - * Sequencer#playSequentially(Animatable[]) playSequentially()} methods if these suit the need, - * but it might be easier in some situations to express the sequence of animations in pairs. + * the {@link AnimatorSet#playTogether(Animator[]) playTogether()} and {@link + * AnimatorSet#playSequentially(Animator[]) playSequentially()} methods if these suit the need, + * but it might be easier in some situations to express the AnimatorSet of animations in pairs. * <p/> * <p>The <code>Builder</code> object cannot be constructed directly, but is rather constructed - * internally via a call to {@link Sequencer#play(Animatable)}.</p> + * internally via a call to {@link AnimatorSet#play(Animator)}.</p> * <p/> - * <p>For example, this sets up a Sequencer to play anim1 and anim2 at the same time, anim3 to + * <p>For example, this sets up a AnimatorSet to play anim1 and anim2 at the same time, anim3 to * play when anim2 finishes, and anim4 to play when anim3 finishes:</p> * <pre> - * Sequencer s = new Sequencer(); + * AnimatorSet s = new AnimatorSet(); * s.play(anim1).with(anim2); * s.play(anim2).before(anim3); * s.play(anim4).after(anim3); * </pre> * <p/> - * <p>Note in the example that both {@link Builder#before(Animatable)} and {@link - * Builder#after(Animatable)} are used. These are just different ways of expressing the same + * <p>Note in the example that both {@link Builder#before(Animator)} and {@link + * Builder#after(Animator)} are used. These are just different ways of expressing the same * relationship and are provided to make it easier to say things in a way that is more natural, * depending on the situation.</p> * <p/> * <p>It is possible to make several calls into the same <code>Builder</code> object to express * multiple relationships. However, note that it is only the animation passed into the initial - * {@link Sequencer#play(Animatable)} method that is the dependency in any of the successive + * {@link AnimatorSet#play(Animator)} method that is the dependency in any of the successive * calls to the <code>Builder</code> object. For example, the following code starts both anim2 * and anim3 when anim1 ends; there is no direct dependency relationship between anim2 and * anim3: * <pre> - * Sequencer s = new Sequencer(); + * AnimatorSet s = new AnimatorSet(); * s.play(anim1).before(anim2).before(anim3); * </pre> * If the desired result is to play anim1 then anim2 then anim3, this code expresses the * relationship correctly:</p> * <pre> - * Sequencer s = new Sequencer(); + * AnimatorSet s = new AnimatorSet(); * s.play(anim1).before(anim2); * s.play(anim2).before(anim3); * </pre> @@ -841,26 +837,26 @@ public final class Sequencer extends Animatable { * <p>Note that it is possible to express relationships that cannot be resolved and will not * result in sensible results. For example, <code>play(anim1).after(anim1)</code> makes no * sense. In general, circular dependencies like this one (or more indirect ones where a depends - * on b, which depends on c, which depends on a) should be avoided. Only create sequences that - * can boil down to a simple, one-way relationship of animations starting with, before, and + * on b, which depends on c, which depends on a) should be avoided. Only create AnimatorSets + * that can boil down to a simple, one-way relationship of animations starting with, before, and * after other, different, animations.</p> */ public class Builder { /** * This tracks the current node being processed. It is supplied to the play() method - * of Sequencer and passed into the constructor of Builder. + * of AnimatorSet and passed into the constructor of Builder. */ private Node mCurrentNode; /** - * package-private constructor. Builders are only constructed by Sequencer, when the + * package-private constructor. Builders are only constructed by AnimatorSet, when the * play() method is called. * * @param anim The animation that is the dependency for the other animations passed into * the other methods of this Builder object. */ - Builder(Animatable anim) { + Builder(Animator anim) { mCurrentNode = mNodeMap.get(anim); if (mCurrentNode == null) { mCurrentNode = new Node(anim); @@ -871,12 +867,12 @@ public final class Sequencer extends Animatable { /** * Sets up the given animation to play at the same time as the animation supplied in the - * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object. + * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object. * * @param anim The animation that will play when the animation supplied to the - * {@link Sequencer#play(Animatable)} method starts. + * {@link AnimatorSet#play(Animator)} method starts. */ - public void with(Animatable anim) { + public void with(Animator anim) { Node node = mNodeMap.get(anim); if (node == null) { node = new Node(anim); @@ -889,13 +885,13 @@ public final class Sequencer extends Animatable { /** * Sets up the given animation to play when the animation supplied in the - * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object + * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object * ends. * * @param anim The animation that will play when the animation supplied to the - * {@link Sequencer#play(Animatable)} method ends. + * {@link AnimatorSet#play(Animator)} method ends. */ - public void before(Animatable anim) { + public void before(Animator anim) { Node node = mNodeMap.get(anim); if (node == null) { node = new Node(anim); @@ -908,13 +904,13 @@ public final class Sequencer extends Animatable { /** * Sets up the given animation to play when the animation supplied in the - * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object + * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object * to start when the animation supplied in this method call ends. * * @param anim The animation whose end will cause the animation supplied to the - * {@link Sequencer#play(Animatable)} method to play. + * {@link AnimatorSet#play(Animator)} method to play. */ - public void after(Animatable anim) { + public void after(Animator anim) { Node node = mNodeMap.get(anim); if (node == null) { node = new Node(anim); @@ -927,15 +923,15 @@ public final class Sequencer extends Animatable { /** * Sets up the animation supplied in the - * {@link Sequencer#play(Animatable)} call that created this <code>Builder</code> object + * {@link AnimatorSet#play(Animator)} call that created this <code>Builder</code> object * to play when the given amount of time elapses. * * @param delay The number of milliseconds that should elapse before the * animation starts. */ public void after(long delay) { - // setup dummy Animator just to run the clock - after(new Animator(delay, 0f, 1f)); + // setup dummy ValueAnimator just to run the clock + after(new ValueAnimator(delay, 0f, 1f)); } } diff --git a/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java index 7d4d104..192ba5c 100644 --- a/core/java/android/animation/Keyframe.java +++ b/core/java/android/animation/Keyframe.java @@ -20,7 +20,7 @@ import android.view.animation.Interpolator; /** * This class holds a time/value pair for an animation. The Keyframe class is used - * by {@link Animator} to define the values that the animation target will have over the course + * by {@link ValueAnimator} to define the values that the animation target will have over the course * of the animation. As the time proceeds from one keyframe to the other, the value of the * target object will animate between the value at the previous keyframe and the value at the * next keyframe. Each keyframe also holds an option {@link android.view.animation.Interpolator} @@ -59,7 +59,7 @@ public class Keyframe implements Cloneable { * the time in this keyframe, and the the value animated from as the time passes the time in * this keyframe. * @param valueType The type of the <code>value</code> object. This is used by the - * {@link #getValue()} functionm, which is queried by {@link Animator} to determine + * {@link #getValue()} functionm, which is queried by {@link ValueAnimator} to determine * the type of {@link TypeEvaluator} to use to interpolate between values. */ private Keyframe(float fraction, Object value, Class valueType) { @@ -239,7 +239,7 @@ public class Keyframe implements Cloneable { } /** - * Gets the type of keyframe. This information is used by Animator to determine the type of + * Gets the type of keyframe. This information is used by ValueAnimator to determine the type of * {@link TypeEvaluator} to use when calculating values between keyframes. The type is based * on the type of Keyframe created. * diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index d144b9c..af47a15 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -21,7 +21,7 @@ import java.util.ArrayList; import android.view.animation.Interpolator; /** - * This class holds a collection of Keyframe objects and is called by Animator to calculate + * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate * values between those keyframes for a given animation. The class internal to the animation * package because it is an implementation detail of how Keyframes are stored and used. */ diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java index 5dfdfbd..d1bc9bd 100644 --- a/core/java/android/animation/LayoutTransition.java +++ b/core/java/android/animation/LayoutTransition.java @@ -32,8 +32,8 @@ import java.util.List; * transitions for a layout container, create a LayoutTransition object and set it on any * ViewGroup by calling {@link ViewGroup#setLayoutTransition(LayoutTransition)}. This will cause * default animations to run whenever items are added to or removed from that container. To specify - * custom animations, use the {@link LayoutTransition#setAnimatable(int, Animatable) - * setAnimatable()} method. + * custom animations, use the {@link LayoutTransition#setAnimator(int, Animator) + * setAnimator()} method. * * <p>One of the core concepts of these transition animations is that there are two core * changes that cause the transition and four different animations that run because of @@ -61,7 +61,7 @@ import java.util.List; * CHANGE_APPEARING animation animates <code>left</code>, <code>top</code>, <code>right</code>, * and <code>bottom</code>. Values for these properties are updated with the pre- and post-layout * values when the transition begins. Custom animations will be similarly populated with - * the target and values being animated, assuming they use PropertyAnimator objects with + * the target and values being animated, assuming they use ObjectAnimator objects with * property names that are known on the target object.</p> */ public class LayoutTransition { @@ -93,21 +93,21 @@ public class LayoutTransition { /** * These variables hold the animations that are currently used to run the transition effects. * These animations are set to defaults, but can be changed to custom animations by - * calls to setAnimatable(). + * calls to setAnimator(). */ - private Animatable mDisappearingAnim = null; - private Animatable mAppearingAnim = null; - private Animatable mChangingAppearingAnim = null; - private Animatable mChangingDisappearingAnim = null; + private Animator mDisappearingAnim = null; + private Animator mAppearingAnim = null; + private Animator mChangingAppearingAnim = null; + private Animator mChangingDisappearingAnim = null; /** * These are the default animations, defined in the constructor, that will be used * unless the user specifies custom animations. */ - private static PropertyAnimator defaultChangeIn; - private static PropertyAnimator defaultChangeOut; - private static PropertyAnimator defaultFadeIn; - private static PropertyAnimator defaultFadeOut; + private static ObjectAnimator defaultChangeIn; + private static ObjectAnimator defaultChangeOut; + private static ObjectAnimator defaultFadeIn; + private static ObjectAnimator defaultFadeOut; /** * The default duration used by all animations. @@ -154,7 +154,7 @@ public class LayoutTransition { * we cache all of the current animations in this map for possible cancellation on * another layout event. */ - private HashMap<View, Animatable> currentAnimations = new HashMap<View, Animatable>(); + private HashMap<View, Animator> currentAnimations = new HashMap<View, Animator>(); /** * This hashmap is used to track the listeners that have been added to the children of @@ -194,7 +194,7 @@ public class LayoutTransition { PropertyValuesHolder<Integer> pvhTop = new PropertyValuesHolder<Integer>("top", 0, 1); PropertyValuesHolder<Integer> pvhRight = new PropertyValuesHolder<Integer>("right", 0, 1); PropertyValuesHolder<Integer> pvhBottom = new PropertyValuesHolder<Integer>("bottom", 0, 1); - defaultChangeIn = new PropertyAnimator<PropertyValuesHolder>(DEFAULT_DURATION, this, + defaultChangeIn = new ObjectAnimator<PropertyValuesHolder>(DEFAULT_DURATION, this, pvhLeft, pvhTop, pvhRight, pvhBottom); defaultChangeIn.setStartDelay(mChangingAppearingDelay); defaultChangeIn.setInterpolator(mChangingAppearingInterpolator); @@ -202,11 +202,11 @@ public class LayoutTransition { defaultChangeOut.setStartDelay(mChangingDisappearingDelay); defaultChangeOut.setInterpolator(mChangingDisappearingInterpolator); defaultFadeIn = - new PropertyAnimator<Float>(DEFAULT_DURATION, this, "alpha", 0f, 1f); + new ObjectAnimator<Float>(DEFAULT_DURATION, this, "alpha", 0f, 1f); defaultFadeIn.setStartDelay(mAppearingDelay); defaultFadeIn.setInterpolator(mAppearingInterpolator); defaultFadeOut = - new PropertyAnimator<Float>(DEFAULT_DURATION, this, "alpha", 1f, 0f); + new ObjectAnimator<Float>(DEFAULT_DURATION, this, "alpha", 1f, 0f); defaultFadeOut.setStartDelay(mDisappearingDelay); defaultFadeOut.setInterpolator(mDisappearingInterpolator); } @@ -240,7 +240,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose start * delay is being set. * @param delay The length of time, in milliseconds, to delay before starting the animation. - * @see android.animation.Animatable#setStartDelay(long) + * @see Animator#setStartDelay(long) */ public void setStartDelay(int transitionType, long delay) { switch (transitionType) { @@ -268,7 +268,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose start * delay is returned. * @return long The start delay of the specified animation. - * @see android.animation.Animatable#getStartDelay() + * @see Animator#getStartDelay() */ public long getStartDelay(int transitionType) { switch (transitionType) { @@ -294,7 +294,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is being set. * @param duration The length of time, in milliseconds, that the specified animation should run. - * @see android.animation.Animatable#setDuration(long) + * @see Animator#setDuration(long) */ public void setDuration(int transitionType, long duration) { switch (transitionType) { @@ -322,7 +322,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is returned. * @return long The duration of the specified animation. - * @see android.animation.Animatable#getDuration() + * @see Animator#getDuration() */ public long getDuration(int transitionType) { switch (transitionType) { @@ -387,7 +387,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is being set. * @param interpolator The interpolator that the specified animation should use. - * @see android.animation.Animatable#setInterpolator(android.view.animation.Interpolator) + * @see Animator#setInterpolator(android.view.animation.Interpolator) */ public void setInterpolator(int transitionType, Interpolator interpolator) { switch (transitionType) { @@ -415,7 +415,7 @@ public class LayoutTransition { * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is being set. * @return Interpolator The interpolator that the specified animation uses. - * @see android.animation.Animatable#setInterpolator(android.view.animation.Interpolator) + * @see Animator#setInterpolator(android.view.animation.Interpolator) */ public Interpolator getInterpolator(int transitionType) { switch (transitionType) { @@ -434,11 +434,11 @@ public class LayoutTransition { /** * Sets the animation used during one of the transition types that may run. Any - * Animatable object can be used, but to be most useful in the context of layout - * transitions, the animation should either be a PropertyAnimator or a Sequencer - * of animations including PropertyAnimators. Also, these PropertyAnimator objects + * Animator object can be used, but to be most useful in the context of layout + * transitions, the animation should either be a ObjectAnimator or a AnimatorSet + * of animations including PropertyAnimators. Also, these ObjectAnimator objects * should be able to get and set values on their target objects automatically. For - * example, a PropertyAnimator that animates the property "left" is able to set and get the + * example, a ObjectAnimator that animates the property "left" is able to set and get the * <code>left</code> property from the View objects being animated by the layout * transition. The transition works by setting target objects and properties * dynamically, according to the pre- and post-layoout values of those objects, so @@ -454,26 +454,26 @@ public class LayoutTransition { * object (presumably 1) as its starting and ending value when the animation begins. * Animations which need to use values at the beginning and end that may not match the * values queried when the transition begins may need to use a different mechanism - * than a standard PropertyAnimator object.</p> + * than a standard ObjectAnimator object.</p> * * @param transitionType one of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is being set. - * @param animatable The animation being assigned. + * @param animator The animation being assigned. */ - public void setAnimatable(int transitionType, Animatable animatable) { + public void setAnimator(int transitionType, Animator animator) { switch (transitionType) { case CHANGE_APPEARING: - mChangingAppearingAnim = (animatable != null) ? animatable : defaultChangeIn; + mChangingAppearingAnim = (animator != null) ? animator : defaultChangeIn; break; case CHANGE_DISAPPEARING: - mChangingDisappearingAnim = (animatable != null) ? animatable : defaultChangeOut; + mChangingDisappearingAnim = (animator != null) ? animator : defaultChangeOut; break; case APPEARING: - mAppearingAnim = (animatable != null) ? animatable : defaultFadeIn; + mAppearingAnim = (animator != null) ? animator : defaultFadeIn; break; case DISAPPEARING: - mDisappearingAnim = (animatable != null) ? animatable : defaultFadeOut; + mDisappearingAnim = (animator != null) ? animator : defaultFadeOut; break; } } @@ -484,10 +484,10 @@ public class LayoutTransition { * @param transitionType one of {@link #CHANGE_APPEARING}, {@link #CHANGE_DISAPPEARING}, * {@link #APPEARING}, or {@link #DISAPPEARING}, which determines the animation whose * duration is being set. - * @return Animatable The animation being used for the given transition type. - * @see #setAnimatable(int, Animatable) + * @return Animator The animation being used for the given transition type. + * @see #setAnimator(int, Animator) */ - public Animatable getAnimatable(int transitionType) { + public Animator getAnimator(int transitionType) { switch (transitionType) { case CHANGE_APPEARING: return mChangingAppearingAnim; @@ -529,21 +529,21 @@ public class LayoutTransition { if (child != newView) { // If there's an animation running on this view already, cancel it - Animatable currentAnimation = currentAnimations.get(child); + Animator currentAnimation = currentAnimations.get(child); if (currentAnimation != null) { currentAnimation.cancel(); currentAnimations.remove(child); } // Make a copy of the appropriate animation - final Animatable anim = (changeReason == APPEARING) ? + final Animator anim = (changeReason == APPEARING) ? mChangingAppearingAnim.clone() : mChangingDisappearingAnim.clone(); // Set the target object for the animation anim.setTarget(child); - // A PropertyAnimator (or Sequencer of them) can extract start values from + // A ObjectAnimator (or AnimatorSet of them) can extract start values from // its target object anim.setupStartValues(); @@ -574,20 +574,20 @@ public class LayoutTransition { anim.setDuration(duration); // Remove the animation from the cache when it ends - anim.addListener(new AnimatableListenerAdapter() { + anim.addListener(new AnimatorListenerAdapter() { private boolean canceled = false; - public void onAnimationCancel(Animatable animatable) { + public void onAnimationCancel(Animator animator) { // we remove canceled animations immediately, not here canceled = true; } - public void onAnimationEnd(Animatable animatable) { + public void onAnimationEnd(Animator animator) { if (!canceled) { currentAnimations.remove(child); } } }); - if (anim instanceof PropertyAnimator) { - ((PropertyAnimator) anim).setCurrentPlayTime(0); + if (anim instanceof ObjectAnimator) { + ((ObjectAnimator) anim).setCurrentPlayTime(0); } anim.start(); @@ -626,15 +626,15 @@ public class LayoutTransition { * @param child The View being added to the ViewGroup. */ private void runAppearingTransition(final ViewGroup parent, final View child) { - Animatable anim = mAppearingAnim.clone(); + Animator anim = mAppearingAnim.clone(); anim.setTarget(child); anim.setStartDelay(mAppearingDelay); anim.setDuration(mAppearingDuration); - if (anim instanceof PropertyAnimator) { - ((PropertyAnimator) anim).setCurrentPlayTime(0); + if (anim instanceof ObjectAnimator) { + ((ObjectAnimator) anim).setCurrentPlayTime(0); } if (mListeners != null) { - anim.addListener(new AnimatableListenerAdapter() { + anim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd() { for (TransitionListener listener : mListeners) { listener.endTransition(LayoutTransition.this, parent, child, APPEARING); @@ -652,12 +652,12 @@ public class LayoutTransition { * @param child The View being removed from the ViewGroup. */ private void runDisappearingTransition(final ViewGroup parent, final View child) { - Animatable anim = mDisappearingAnim.clone(); + Animator anim = mDisappearingAnim.clone(); anim.setStartDelay(mDisappearingDelay); anim.setDuration(mDisappearingDuration); anim.setTarget(child); if (mListeners != null) { - anim.addListener(new AnimatableListenerAdapter() { + anim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd() { for (TransitionListener listener : mListeners) { listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING); @@ -665,8 +665,8 @@ public class LayoutTransition { } }); } - if (anim instanceof PropertyAnimator) { - ((PropertyAnimator) anim).setCurrentPlayTime(0); + if (anim instanceof ObjectAnimator) { + ((ObjectAnimator) anim).setCurrentPlayTime(0); } anim.start(); } diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/ObjectAnimator.java index e555cc6..6cb90be 100644 --- a/core/java/android/animation/PropertyAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -21,13 +21,13 @@ import android.util.Log; import java.lang.reflect.Method; /** - * This subclass of {@link Animator} provides support for animating properties on target objects. + * This subclass of {@link ValueAnimator} provides support for animating properties on target objects. * The constructors of this class take parameters to define the target object that will be animated * as well as the name of the property that will be animated. Appropriate set/get functions * are then determined internally and the animation will call these functions as necessary to * animate the property. */ -public final class PropertyAnimator<T> extends Animator<T> { +public final class ObjectAnimator<T> extends ValueAnimator<T> { // The target object on which the property exists, set in the constructor private Object mTarget; @@ -47,7 +47,7 @@ public final class PropertyAnimator<T> extends Animator<T> { * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to * the setter function will fail.</p> * - * <p>If this PropertyAnimator has been set up to animate several properties together, + * <p>If this ObjectAnimator has been set up to animate several properties together, * using more than one PropertyValuesHolder objects, then setting the propertyName simply * sets the propertyName in the first of those PropertyValuesHolder objects.</p> * @@ -101,18 +101,18 @@ public final class PropertyAnimator<T> extends Animator<T> { try { returnVal = mTarget.getClass().getMethod(setterName, args); } catch (NoSuchMethodException e) { - Log.e("PropertyAnimator", + Log.e("ObjectAnimator", "Couldn't find setter/getter for property " + mPropertyName + ": " + e); } return returnVal; } /** - * Creates a new PropertyAnimator object. This default constructor is primarily for + * Creates a new ObjectAnimator object. This default constructor is primarily for * use internally; the other constructors which take parameters are more generally * useful. */ - public PropertyAnimator() { + public ObjectAnimator() { } /** @@ -128,7 +128,7 @@ public final class PropertyAnimator<T> extends Animator<T> { * is assumed to be the final value being animated to, and the initial value will be * derived on the fly. */ - public PropertyAnimator(long duration, Object target, String propertyName, T...values) { + public ObjectAnimator(long duration, Object target, String propertyName, T...values) { super(duration, (T[]) values); mTarget = target; setPropertyName(propertyName); @@ -136,7 +136,7 @@ public final class PropertyAnimator<T> extends Animator<T> { /** * A constructor that takes <code>PropertyValueHolder</code> values. This constructor should - * be used when animating several properties at once with the same PropertyAnimator, since + * be used when animating several properties at once with the same ObjectAnimator, since * PropertyValuesHolder allows you to associate a set of animation values with a property * name. * @@ -148,7 +148,7 @@ public final class PropertyAnimator<T> extends Animator<T> { * @param values The PropertyValuesHolder objects which hold each the property name and values * to animate that property between. */ - public PropertyAnimator(long duration, Object target, PropertyValuesHolder...values) { + public ObjectAnimator(long duration, Object target, PropertyValuesHolder...values) { super(duration); setValues(values); mTarget = target; @@ -239,8 +239,8 @@ public final class PropertyAnimator<T> extends Animator<T> { } @Override - public PropertyAnimator clone() { - final PropertyAnimator anim = (PropertyAnimator) super.clone(); + public ObjectAnimator clone() { + final ObjectAnimator anim = (ObjectAnimator) super.clone(); return anim; } } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index b6ff54e..1d46123 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -27,31 +27,31 @@ import java.util.concurrent.locks.ReentrantReadWriteLock; /** * This class holds information about a property and the values that that property * should take on during an animation. PropertyValuesHolder objects can be used to create - * animations with Animator or PropertyAnimator that operate on several different properties + * animations with ValueAnimator or ObjectAnimator that operate on several different properties * in parallel. */ public class PropertyValuesHolder<T> implements Cloneable { /** * The name of the property associated with the values. This need not be a real property, - * unless this object is being used with PropertyAnimator. But this is the name by which - * aniamted values are looked up with getAnimatedValue(String) in Animator. + * unless this object is being used with ObjectAnimator. But this is the name by which + * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator. */ private String mPropertyName; /** - * The setter function, if needed. PropertyAnimator hands off this functionality to + * The setter function, if needed. ObjectAnimator hands off this functionality to * PropertyValuesHolder, since it holds all of the per-property information. This * property can be manually set via setSetter(). Otherwise, it is automatically - * derived when the animation starts in setupSetterAndGetter() if using PropertyAnimator. + * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. */ private Method mSetter = null; /** - * The getter function, if needed. PropertyAnimator hands off this functionality to + * The getter function, if needed. ObjectAnimator hands off this functionality to * PropertyValuesHolder, since it holds all of the per-property information. This * property can be manually set via setSetter(). Otherwise, it is automatically - * derived when the animation starts in setupSetterAndGetter() if using PropertyAnimator. + * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. * The getter is only derived and used if one of the values is null. */ private Method mGetter = null; @@ -112,16 +112,16 @@ public class PropertyValuesHolder<T> implements Cloneable { /** * The value most recently calculated by calculateValue(). This is set during - * that function and might be retrieved later either by Animator.animatedValue() or - * by the property-setting logic in PropertyAnimator.animatedValue(). + * that function and might be retrieved later either by ValueAnimator.animatedValue() or + * by the property-setting logic in ObjectAnimator.animatedValue(). */ private Object mAnimatedValue; /** * Constructs a PropertyValuesHolder object with just a set of values. This constructor - * is typically not used when animating objects with PropertyAnimator, because that + * is typically not used when animating objects with ObjectAnimator, because that * object needs distinct and meaningful property names. Simpler animations of one - * set of values using Animator may use this constructor, however, because no + * set of values using ValueAnimator may use this constructor, however, because no * distinguishing name is needed. * @param values The set of values to animate between. If there is only one value, it * is assumed to be the final value being animated to, and the initial value will be @@ -141,14 +141,14 @@ public class PropertyValuesHolder<T> implements Cloneable { * on the object. Also, if any value is null, the value will be filled in when the animation * starts in the same way. This mechanism of automatically getting null values only works * if the PropertyValuesHolder object is used in conjunction - * {@link android.animation.PropertyAnimator}, and with a getter function either + * {@link ObjectAnimator}, and with a getter function either * derived automatically from <code>propertyName</code> or set explicitly via * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has * no way of determining what the value should be. * @param propertyName The name of the property associated with this set of values. This - * can be the actual property name to be used when using a PropertyAnimator object, or + * can be the actual property name to be used when using a ObjectAnimator object, or * just a name used to get animated values, such as if this object is used with an - * Animator object. + * ValueAnimator object. * @param values The set of values to animate between. */ public PropertyValuesHolder(String propertyName, T... values) { @@ -163,7 +163,7 @@ public class PropertyValuesHolder<T> implements Cloneable { * on the object. Also, if any value is null, the value will be filled in when the animation * starts in the same way. This mechanism of automatically getting null values only works * if the PropertyValuesHolder object is used in conjunction - * {@link android.animation.PropertyAnimator}, and with a getter function either + * {@link ObjectAnimator}, and with a getter function either * derived automatically from <code>propertyName</code> or set explicitly via * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has * no way of determining what the value should be. @@ -331,7 +331,7 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** - * Internal function (called from PropertyAnimator) to set up the setter and getter + * Internal function (called from ObjectAnimator) to set up the setter and getter * prior to running the animation. If the setter has not been manually set for this * object, it will be derived automatically given the property name, target object, and * types of values supplied. If no getter has been set, it will be supplied iff any of the @@ -383,7 +383,7 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** - * This function is called by PropertyAnimator when setting the start values for an animation. + * This function is called by ObjectAnimator when setting the start values for an animation. * The start values are set according to the current values in the target object. The * property whose value is extracted is whatever is specified by the propertyName of this * PropertyValuesHolder object. @@ -395,7 +395,7 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** - * This function is called by PropertyAnimator when setting the end values for an animation. + * This function is called by ObjectAnimator when setting the end values for an animation. * The end values are set according to the current values in the target object. The * property whose value is extracted is whatever is specified by the propertyName of this * PropertyValuesHolder object. @@ -420,8 +420,8 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** * Internal function to set the value on the target object, using the setter set up - * earlier on this PropertyValuesHolder object. This function is called by PropertyAnimator - * to handle turning the value calculated by Animator into a value set on the object + * earlier on this PropertyValuesHolder object. This function is called by ObjectAnimator + * to handle turning the value calculated by ValueAnimator into a value set on the object * according to the name of the property. * @param target The target object on which the value is set */ @@ -439,7 +439,7 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** - * Internal function, called by Animator, to set up the TypeEvaluator that will be used + * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used * to calculate animated values. */ void init() { @@ -466,7 +466,7 @@ public class PropertyValuesHolder<T> implements Cloneable { /** * Function used to calculate the value according to the evaluator set up for - * this PropertyValuesHolder object. This function is called by Animator.animateValue(). + * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). * * @param fraction The elapsed, interpolated fraction of the animation. * @return The calculated value at this point in the animation. @@ -483,7 +483,7 @@ public class PropertyValuesHolder<T> implements Cloneable { * approach is more direct, and is especially useful when a function must be called that does * not correspond to the convention of <code>setName()</code>. For example, if a function * called <code>offset()</code> is to be called with the animated values, there is no way - * to tell <code>PropertyAnimator</code> how to call that function simply through a property + * to tell <code>ObjectAnimator</code> how to call that function simply through a property * name, so a setter method should be supplied instead. * * <p>Note that the setter function must take the same parameter type as the @@ -511,7 +511,7 @@ public class PropertyValuesHolder<T> implements Cloneable { * approach is more direct, and is especially useful when a function must be called that does * not correspond to the convention of <code>setName()</code>. For example, if a function * called <code>offset()</code> is to be called to get an initial value, there is no way - * to tell <code>PropertyAnimator</code> how to call that function simply through a property + * to tell <code>ObjectAnimator</code> how to call that function simply through a property * name, so a getter method should be supplied instead. * * <p>Note that the getter method is only called whether supplied here or derived @@ -569,7 +569,7 @@ public class PropertyValuesHolder<T> implements Cloneable { } /** - * Internal function, called by Animator and PropertyAnimator, to retrieve the value + * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value * most recently calculated in calculateValue(). * @return */ diff --git a/core/java/android/animation/TypeEvaluator.java b/core/java/android/animation/TypeEvaluator.java index 6150e00..fa49175 100644 --- a/core/java/android/animation/TypeEvaluator.java +++ b/core/java/android/animation/TypeEvaluator.java @@ -17,12 +17,12 @@ package android.animation; /** - * Interface for use with the {@link Animator#setEvaluator(TypeEvaluator)} function. Evaluators + * Interface for use with the {@link ValueAnimator#setEvaluator(TypeEvaluator)} function. Evaluators * allow developers to create animations on arbitrary property types, by allowing them to supply * custom evaulators for types that are not automatically understood and used by the animation * system. * - * @see Animator#setEvaluator(TypeEvaluator) + * @see ValueAnimator#setEvaluator(TypeEvaluator) */ public interface TypeEvaluator { diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java new file mode 100755 index 0000000..54a8e4b --- /dev/null +++ b/core/java/android/animation/ValueAnimator.java @@ -0,0 +1,972 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.animation; + +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +import java.util.ArrayList; +import java.util.HashMap; + +/** + * This class provides a simple timing engine for running animations + * which calculate animated values and set them on target objects. + * + * <p>There is a single timing pulse that all animations use. It runs in a + * custom handler to ensure that property changes happen on the UI thread.</p> + * + * <p>By default, ValueAnimator uses non-linear time interpolation, via the + * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates + * out of an animation. This behavior can be changed by calling + * {@link ValueAnimator#setInterpolator(Interpolator)}.</p> + */ +public class ValueAnimator<T> extends Animator { + + /** + * Internal constants + */ + + /* + * The default amount of time in ms between animation frames + */ + private static final long DEFAULT_FRAME_DELAY = 30; + + /** + * Messages sent to timing handler: START is sent when an animation first begins, FRAME is sent + * by the handler to itself to process the next animation frame + */ + private static final int ANIMATION_START = 0; + private static final int ANIMATION_FRAME = 1; + + /** + * Values used with internal variable mPlayingState to indicate the current state of an + * animation. + */ + private static final int STOPPED = 0; // Not yet playing + private static final int RUNNING = 1; // Playing normally + private static final int CANCELED = 2; // cancel() called - need to end it + private static final int ENDED = 3; // end() called - need to end it + private static final int SEEKED = 4; // Seeked to some time value + + /** + * Internal variables + * NOTE: This object implements the clone() method, making a deep copy of any referenced + * objects. As other non-trivial fields are added to this class, make sure to add logic + * to clone() to make deep copies of them. + */ + + // The first time that the animation's animateFrame() method is called. This time is used to + // determine elapsed time (and therefore the elapsed fraction) in subsequent calls + // to animateFrame() + private long mStartTime; + + /** + * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked + * to a value. + */ + private long mSeekTime = -1; + + // The static sAnimationHandler processes the internal timing loop on which all animations + // are based + private static AnimationHandler sAnimationHandler; + + // The static list of all active animations + private static final ArrayList<ValueAnimator> sAnimations = new ArrayList<ValueAnimator>(); + + // The set of animations to be started on the next animation frame + private static final ArrayList<ValueAnimator> sPendingAnimations = new ArrayList<ValueAnimator>(); + + // The time interpolator to be used if none is set on the animation + private static final Interpolator sDefaultInterpolator = new AccelerateDecelerateInterpolator(); + + // type evaluators for the three primitive types handled by this implementation + private static final TypeEvaluator sIntEvaluator = new IntEvaluator(); + private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator(); + private static final TypeEvaluator sDoubleEvaluator = new DoubleEvaluator(); + + /** + * Used to indicate whether the animation is currently playing in reverse. This causes the + * elapsed fraction to be inverted to calculate the appropriate values. + */ + private boolean mPlayingBackwards = false; + + /** + * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the + * repeatCount (if repeatCount!=INFINITE), the animation ends + */ + private int mCurrentIteration = 0; + + /** + * Tracks whether a startDelay'd animation has begun playing through the startDelay. + */ + private boolean mStartedDelay = false; + + /** + * Tracks the time at which the animation began playing through its startDelay. This is + * different from the mStartTime variable, which is used to track when the animation became + * active (which is when the startDelay expired and the animation was added to the active + * animations list). + */ + private long mDelayStartTime; + + /** + * Flag that represents the current state of the animation. Used to figure out when to start + * an animation (if state == STOPPED). Also used to end an animation that + * has been cancel()'d or end()'d since the last animation frame. Possible values are + * STOPPED, RUNNING, ENDED, CANCELED. + */ + private int mPlayingState = STOPPED; + + /** + * Internal collections used to avoid set collisions as animations start and end while being + * processed. + */ + private static final ArrayList<ValueAnimator> sEndingAnims = new ArrayList<ValueAnimator>(); + private static final ArrayList<ValueAnimator> sDelayedAnims = new ArrayList<ValueAnimator>(); + private static final ArrayList<ValueAnimator> sReadyAnims = new ArrayList<ValueAnimator>(); + + /** + * Flag that denotes whether the animation is set up and ready to go. Used to + * set up animation that has not yet been started. + */ + boolean mInitialized = false; + + // + // Backing variables + // + + // How long the animation should last in ms + private long mDuration; + + // The amount of time in ms to delay starting the animation after start() is called + private long mStartDelay = 0; + + // The number of milliseconds between animation frames + private static long sFrameDelay = DEFAULT_FRAME_DELAY; + + // The number of times the animation will repeat. The default is 0, which means the animation + // will play only once + private int mRepeatCount = 0; + + /** + * The type of repetition that will occur when repeatMode is nonzero. RESTART means the + * animation will start from the beginning on every new cycle. REVERSE means the animation + * will reverse directions on each iteration. + */ + private int mRepeatMode = RESTART; + + /** + * The time interpolator to be used. The elapsed fraction of the animation will be passed + * through this interpolator to calculate the interpolated fraction, which is then used to + * calculate the animated values. + */ + private Interpolator mInterpolator = sDefaultInterpolator; + + /** + * The set of listeners to be sent events through the life of an animation. + */ + private ArrayList<AnimatorUpdateListener> mUpdateListeners = null; + + /** + * The property/value sets being animated. + */ + PropertyValuesHolder[] mValues; + + /** + * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values + * by property name during calls to getAnimatedValue(String). + */ + HashMap<String, PropertyValuesHolder> mValuesMap; + + /** + * Public constants + */ + + /** + * When the animation reaches the end and <code>repeatCount</code> is INFINITE + * or a positive value, the animation restarts from the beginning. + */ + public static final int RESTART = 1; + /** + * When the animation reaches the end and <code>repeatCount</code> is INFINITE + * or a positive value, the animation reverses direction on every iteration. + */ + public static final int REVERSE = 2; + /** + * This value used used with the {@link #setRepeatCount(int)} property to repeat + * the animation indefinitely. + */ + public static final int INFINITE = -1; + + /** + * Creates a new ValueAnimator object. This default constructor is primarily for + * use internally; the other constructors which take parameters are more generally + * useful. + */ + public ValueAnimator() { + } + + /** + * Constructs an ValueAnimator object with the specified duration and set of + * values. If the values are a set of PropertyValuesHolder objects, then these objects + * define the potentially multiple properties being animated and the values the properties are + * animated between. Otherwise, the values define a single set of values animated between. + * + * @param duration The length of the animation, in milliseconds. + * @param values The set of values to animate between. If these values are not + * PropertyValuesHolder objects, then there should be more than one value, since the values + * determine the interval to animate between. + */ + public ValueAnimator(long duration, T...values) { + mDuration = duration; + if (values.length > 0) { + setValues(values); + } + } + + /** + * Sets the values, per property, being animated between. This function is called internally + * by the constructors of ValueAnimator that take a list of values. But an ValueAnimator can + * be constructed without values and this method can be called to set the values manually + * instead. + * + * @param values The set of values, per property, being animated between. + */ + public void setValues(PropertyValuesHolder... values) { + int numValues = values.length; + mValues = values; + mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); + for (int i = 0; i < numValues; ++i) { + PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i]; + mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); + } + } + + /** + * Returns the values that this ValueAnimator animates between. These values are stored in + * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list + * of value objects instead. + * + * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the + * values, per property, that define the animation. + */ + public PropertyValuesHolder[] getValues() { + return mValues; + } + + /** + * Sets the values to animate between for this animation. If <code>values</code> is + * a set of PropertyValuesHolder objects, these objects will become the set of properties + * animated and the values that those properties are animated between. Otherwise, this method + * will set only one set of values for the ValueAnimator. Also, if the values are not + * PropertyValuesHolder objects and if there are already multiple sets of + * values defined for this ValueAnimator via + * more than one PropertyValuesHolder objects, this method will set the values for + * the first of those objects. + * + * @param values The set of values to animate between. + */ + public void setValues(T... values) { + if (mValues == null || mValues.length == 0) { + setValues(new PropertyValuesHolder[]{ + new PropertyValuesHolder("", (Object[])values)}); + } else { + PropertyValuesHolder valuesHolder = mValues[0]; + valuesHolder.setValues(values); + } + } + + /** + * This function is called immediately before processing the first animation + * frame of an animation. If there is a nonzero <code>startDelay</code>, the + * function is called after that delay ends. + * It takes care of the final initialization steps for the + * animation. + * + * <p>Overrides of this method should call the superclass method to ensure + * that internal mechanisms for the animation are set up correctly.</p> + */ + void initAnimation() { + if (!mInitialized) { + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].init(); + } + mCurrentIteration = 0; + mInitialized = true; + } + } + + + /** + * Sets the length of the animation. + * + * @param duration The length of the animation, in milliseconds. + */ + public void setDuration(long duration) { + mDuration = duration; + } + + /** + * Gets the length of the animation. + * + * @return The length of the animation, in milliseconds. + */ + public long getDuration() { + return mDuration; + } + + /** + * Sets the position of the animation to the specified point in time. This time should + * be between 0 and the total duration of the animation, including any repetition. If + * the animation has not yet been started, then it will not advance forward after it is + * set to this time; it will simply set the time to this value and perform any appropriate + * actions based on that time. If the animation is already running, then setCurrentPlayTime() + * will set the current playing time to this value and continue playing from that point. + * + * @param playTime The time, in milliseconds, to which the animation is advanced or rewound. + */ + public void setCurrentPlayTime(long playTime) { + initAnimation(); + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + if (mPlayingState != RUNNING) { + mSeekTime = playTime; + mPlayingState = SEEKED; + } + mStartTime = currentTime - playTime; + animationFrame(currentTime); + } + + /** + * Gets the current position of the animation in time, which is equal to the current + * time minus the time that the animation started. An animation that is not yet started will + * return a value of zero. + * + * @return The current position in time of the animation. + */ + public long getCurrentPlayTime() { + if (!mInitialized || mPlayingState == STOPPED) { + return 0; + } + return AnimationUtils.currentAnimationTimeMillis() - mStartTime; + } + + /** + * This custom, static handler handles the timing pulse that is shared by + * all active animations. This approach ensures that the setting of animation + * values will happen on the UI thread and that all animations will share + * the same times for calculating their values, which makes synchronizing + * animations possible. + * + */ + private static class AnimationHandler extends Handler { + /** + * There are only two messages that we care about: ANIMATION_START and + * ANIMATION_FRAME. The START message is sent when an animation's start() + * method is called. It cannot start synchronously when start() is called + * because the call may be on the wrong thread, and it would also not be + * synchronized with other animations because it would not start on a common + * timing pulse. So each animation sends a START message to the handler, which + * causes the handler to place the animation on the active animations queue and + * start processing frames for that animation. + * The FRAME message is the one that is sent over and over while there are any + * active animations to process. + */ + @Override + public void handleMessage(Message msg) { + boolean callAgain = true; + switch (msg.what) { + // TODO: should we avoid sending frame message when starting if we + // were already running? + case ANIMATION_START: + if (sAnimations.size() > 0 || sDelayedAnims.size() > 0) { + callAgain = false; + } + // pendingAnims holds any animations that have requested to be started + // We're going to clear sPendingAnimations, but starting animation may + // cause more to be added to the pending list (for example, if one animation + // starting triggers another starting). So we loop until sPendingAnimations + // is empty. + while (sPendingAnimations.size() > 0) { + ArrayList<ValueAnimator> pendingCopy = + (ArrayList<ValueAnimator>) sPendingAnimations.clone(); + sPendingAnimations.clear(); + int count = pendingCopy.size(); + for (int i = 0; i < count; ++i) { + ValueAnimator anim = pendingCopy.get(i); + // If the animation has a startDelay, place it on the delayed list + if (anim.mStartDelay == 0 || anim.mPlayingState == ENDED || + anim.mPlayingState == CANCELED) { + anim.startAnimation(); + } else { + sDelayedAnims.add(anim); + } + } + } + // fall through to process first frame of new animations + case ANIMATION_FRAME: + // currentTime holds the common time for all animations processed + // during this frame + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + + // First, process animations currently sitting on the delayed queue, adding + // them to the active animations if they are ready + int numDelayedAnims = sDelayedAnims.size(); + for (int i = 0; i < numDelayedAnims; ++i) { + ValueAnimator anim = sDelayedAnims.get(i); + if (anim.delayedAnimationFrame(currentTime)) { + sReadyAnims.add(anim); + } + } + int numReadyAnims = sReadyAnims.size(); + if (numReadyAnims > 0) { + for (int i = 0; i < numReadyAnims; ++i) { + ValueAnimator anim = sReadyAnims.get(i); + anim.startAnimation(); + sDelayedAnims.remove(anim); + } + sReadyAnims.clear(); + } + + // Now process all active animations. The return value from animationFrame() + // tells the handler whether it should now be ended + int numAnims = sAnimations.size(); + for (int i = 0; i < numAnims; ++i) { + ValueAnimator anim = sAnimations.get(i); + if (anim.animationFrame(currentTime)) { + sEndingAnims.add(anim); + } + } + if (sEndingAnims.size() > 0) { + for (int i = 0; i < sEndingAnims.size(); ++i) { + sEndingAnims.get(i).endAnimation(); + } + sEndingAnims.clear(); + } + + // If there are still active or delayed animations, call the handler again + // after the frameDelay + if (callAgain && (!sAnimations.isEmpty() || !sDelayedAnims.isEmpty())) { + sendEmptyMessageDelayed(ANIMATION_FRAME, sFrameDelay); + } + break; + } + } + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + * + * @return the number of milliseconds to delay running the animation + */ + public long getStartDelay() { + return mStartDelay; + } + + /** + * The amount of time, in milliseconds, to delay starting the animation after + * {@link #start()} is called. + + * @param startDelay The amount of the delay, in milliseconds + */ + public void setStartDelay(long startDelay) { + this.mStartDelay = startDelay; + } + + /** + * The amount of time, in milliseconds, between each frame of the animation. This is a + * requested time that the animation will attempt to honor, but the actual delay between + * frames may be different, depending on system load and capabilities. This is a static + * function because the same delay will be applied to all animations, since they are all + * run off of a single timing loop. + * + * @return the requested time between frames, in milliseconds + */ + public static long getFrameDelay() { + return sFrameDelay; + } + + /** + * The amount of time, in milliseconds, between each frame of the animation. This is a + * requested time that the animation will attempt to honor, but the actual delay between + * frames may be different, depending on system load and capabilities. This is a static + * function because the same delay will be applied to all animations, since they are all + * run off of a single timing loop. + * + * @param frameDelay the requested time between frames, in milliseconds + */ + public static void setFrameDelay(long frameDelay) { + sFrameDelay = frameDelay; + } + + /** + * The most recent value calculated by this <code>ValueAnimator</code> when there is just one + * property being animated. This value is only sensible while the animation is running. The main + * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code> + * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which + * is called during each animation frame, immediately after the value is calculated. + * + * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for + * the single property being animated. If there are several properties being animated + * (specified by several PropertyValuesHolder objects in the constructor), this function + * returns the animated value for the first of those objects. + */ + public Object getAnimatedValue() { + if (mValues != null && mValues.length > 0) { + return mValues[0].getAnimatedValue(); + } + // Shouldn't get here; should always have values unless ValueAnimator was set up wrong + return null; + } + + /** + * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>. + * The main purpose for this read-only property is to retrieve the value from the + * <code>ValueAnimator</code> during a call to + * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which + * is called during each animation frame, immediately after the value is calculated. + * + * @return animatedValue The value most recently calculated for the named property + * by this <code>ValueAnimator</code>. + */ + public Object getAnimatedValue(String propertyName) { + PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); + if (valuesHolder != null) { + return valuesHolder.getAnimatedValue(); + } else { + // At least avoid crashing if called with bogus propertyName + return null; + } + } + + /** + * Sets how many times the animation should be repeated. If the repeat + * count is 0, the animation is never repeated. If the repeat count is + * greater than 0 or {@link #INFINITE}, the repeat mode will be taken + * into account. The repeat count is 0 by default. + * + * @param value the number of times the animation should be repeated + */ + public void setRepeatCount(int value) { + mRepeatCount = value; + } + /** + * Defines how many times the animation should repeat. The default value + * is 0. + * + * @return the number of times the animation should repeat, or {@link #INFINITE} + */ + public int getRepeatCount() { + return mRepeatCount; + } + + /** + * Defines what this animation should do when it reaches the end. This + * setting is applied only when the repeat count is either greater than + * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}. + * + * @param value {@link #RESTART} or {@link #REVERSE} + */ + public void setRepeatMode(int value) { + mRepeatMode = value; + } + + /** + * Defines what this animation should do when it reaches the end. + * + * @return either one of {@link #REVERSE} or {@link #RESTART} + */ + public int getRepeatMode() { + return mRepeatMode; + } + + /** + * Adds a listener to the set of listeners that are sent update events through the life of + * an animation. This method is called on all listeners for every frame of the animation, + * after the values for the animation have been calculated. + * + * @param listener the listener to be added to the current set of listeners for this animation. + */ + public void addUpdateListener(AnimatorUpdateListener listener) { + if (mUpdateListeners == null) { + mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); + } + mUpdateListeners.add(listener); + } + + /** + * Removes a listener from the set listening to frame updates for this animation. + * + * @param listener the listener to be removed from the current set of update listeners + * for this animation. + */ + public void removeUpdateListener(AnimatorUpdateListener listener) { + if (mUpdateListeners == null) { + return; + } + mUpdateListeners.remove(listener); + if (mUpdateListeners.size() == 0) { + mUpdateListeners = null; + } + } + + + /** + * The time interpolator used in calculating the elapsed fraction of this animation. The + * interpolator determines whether the animation runs with linear or non-linear motion, + * such as acceleration and deceleration. The default value is + * {@link android.view.animation.AccelerateDecelerateInterpolator} + * + * @param value the interpolator to be used by this animation + */ + @Override + public void setInterpolator(Interpolator value) { + if (value != null) { + mInterpolator = value; + } + } + + /** + * Returns the timing interpolator that this ValueAnimator uses. + * + * @return The timing interpolator for this ValueAnimator. + */ + public Interpolator getInterpolator() { + return mInterpolator; + } + + /** + * The type evaluator to be used when calculating the animated values of this animation. + * The system will automatically assign a float, int, or double evaluator based on the type + * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values + * are not one of these primitive types, or if different evaluation is desired (such as is + * necessary with int values that represent colors), a custom evaluator needs to be assigned. + * For example, when running an animation on color values, the {@link RGBEvaluator} + * should be used to get correct RGB color interpolation. + * + * <p>If this ValueAnimator has only one set of values being animated between, this evaluator + * will be used for that set. If there are several sets of values being animated, which is + * the case if PropertyValuesHOlder objects were set on the ValueAnimator, then the evaluator + * is assigned just to the first PropertyValuesHolder object.</p> + * + * @param value the evaluator to be used this animation + */ + public void setEvaluator(TypeEvaluator value) { + if (value != null && mValues != null && mValues.length > 0) { + mValues[0].setEvaluator(value); + } + } + + /** + * Start the animation playing. This version of start() takes a boolean flag that indicates + * whether the animation should play in reverse. The flag is usually false, but may be set + * to true if called from the reverse() method/ + * + * @param playBackwards Whether the ValueAnimator should start playing in reverse. + */ + private void start(boolean playBackwards) { + mPlayingBackwards = playBackwards; + if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) { + // This sets the initial value of the animation, prior to actually starting it running + setCurrentPlayTime(getCurrentPlayTime()); + } + mPlayingState = STOPPED; + mStartedDelay = false; + sPendingAnimations.add(this); + if (sAnimationHandler == null) { + sAnimationHandler = new AnimationHandler(); + } + // TODO: does this put too many messages on the queue if the handler + // is already running? + sAnimationHandler.sendEmptyMessage(ANIMATION_START); + } + + @Override + public void start() { + start(false); + } + + @Override + public void cancel() { + if (mListeners != null) { + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationCancel(this); + } + } + // Just set the CANCELED flag - this causes the animation to end the next time a frame + // is processed. + mPlayingState = CANCELED; + } + + @Override + public void end() { + if (!sAnimations.contains(this) && !sPendingAnimations.contains(this)) { + // Special case if the animation has not yet started; get it ready for ending + mStartedDelay = false; + sPendingAnimations.add(this); + if (sAnimationHandler == null) { + sAnimationHandler = new AnimationHandler(); + } + sAnimationHandler.sendEmptyMessage(ANIMATION_START); + } + // Just set the ENDED flag - this causes the animation to end the next time a frame + // is processed. + mPlayingState = ENDED; + } + + @Override + public boolean isRunning() { + // ENDED or CANCELED indicate that it has been ended or canceled, but not processed yet + return (mPlayingState == RUNNING || mPlayingState == ENDED || mPlayingState == CANCELED); + } + + /** + * Plays the ValueAnimator in reverse. If the animation is already running, + * it will stop itself and play backwards from the point reached when reverse was called. + * If the animation is not currently running, then it will start from the end and + * play backwards. This behavior is only set for the current animation; future playing + * of the animation will use the default behavior of playing forward. + */ + public void reverse() { + mPlayingBackwards = !mPlayingBackwards; + if (mPlayingState == RUNNING) { + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + long currentPlayTime = currentTime - mStartTime; + long timeLeft = mDuration - currentPlayTime; + mStartTime = currentTime - timeLeft; + } else { + start(true); + } + } + + /** + * Called internally to end an animation by removing it from the animations list. Must be + * called on the UI thread. + */ + private void endAnimation() { + sAnimations.remove(this); + mPlayingState = STOPPED; + if (mListeners != null) { + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationEnd(this); + } + } + } + + /** + * Called internally to start an animation by adding it to the active animations list. Must be + * called on the UI thread. + */ + private void startAnimation() { + initAnimation(); + sAnimations.add(this); + if (mListeners != null) { + ArrayList<AnimatorListener> tmpListeners = + (ArrayList<AnimatorListener>) mListeners.clone(); + for (AnimatorListener listener : tmpListeners) { + listener.onAnimationStart(this); + } + } + } + + /** + * Internal function called to process an animation frame on an animation that is currently + * sleeping through its <code>startDelay</code> phase. The return value indicates whether it + * should be woken up and put on the active animations queue. + * + * @param currentTime The current animation time, used to calculate whether the animation + * has exceeded its <code>startDelay</code> and should be started. + * @return True if the animation's <code>startDelay</code> has been exceeded and the animation + * should be added to the set of active animations. + */ + private boolean delayedAnimationFrame(long currentTime) { + if (mPlayingState == CANCELED || mPlayingState == ENDED) { + // end the delay, process an animation frame to actually cancel it + return true; + } + if (!mStartedDelay) { + mStartedDelay = true; + mDelayStartTime = currentTime; + } else { + long deltaTime = currentTime - mDelayStartTime; + if (deltaTime > mStartDelay) { + // startDelay ended - start the anim and record the + // mStartTime appropriately + mStartTime = currentTime - (deltaTime - mStartDelay); + mPlayingState = RUNNING; + return true; + } + } + return false; + } + + /** + * This internal function processes a single animation frame for a given animation. The + * currentTime parameter is the timing pulse sent by the handler, used to calculate the + * elapsed duration, and therefore + * the elapsed fraction, of the animation. The return value indicates whether the animation + * should be ended (which happens when the elapsed time of the animation exceeds the + * animation's duration, including the repeatCount). + * + * @param currentTime The current time, as tracked by the static timing handler + * @return true if the animation's duration, including any repetitions due to + * <code>repeatCount</code> has been exceeded and the animation should be ended. + */ + private boolean animationFrame(long currentTime) { + boolean done = false; + + if (mPlayingState == STOPPED) { + mPlayingState = RUNNING; + if (mSeekTime < 0) { + mStartTime = currentTime; + } else { + mStartTime = currentTime - mSeekTime; + // Now that we're playing, reset the seek time + mSeekTime = -1; + } + } + switch (mPlayingState) { + case RUNNING: + case SEEKED: + float fraction = (float)(currentTime - mStartTime) / mDuration; + if (fraction >= 1f) { + if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { + // Time to repeat + if (mListeners != null) { + for (AnimatorListener listener : mListeners) { + listener.onAnimationRepeat(this); + } + } + ++mCurrentIteration; + if (mRepeatMode == REVERSE) { + mPlayingBackwards = mPlayingBackwards ? false : true; + } + // TODO: doesn't account for fraction going Wayyyyy over 1, like 2+ + fraction = fraction - 1f; + mStartTime += mDuration; + } else { + done = true; + fraction = Math.min(fraction, 1.0f); + } + } + if (mPlayingBackwards) { + fraction = 1f - fraction; + } + animateValue(fraction); + break; + case ENDED: + // The final value set on the target varies, depending on whether the animation + // was supposed to repeat an odd number of times + if (mRepeatCount > 0 && (mRepeatCount & 0x01) == 1) { + animateValue(0f); + } else { + animateValue(1f); + } + // Fall through to set done flag + case CANCELED: + done = true; + mPlayingState = STOPPED; + break; + } + + return done; + } + + /** + * This method is called with the elapsed fraction of the animation during every + * animation frame. This function turns the elapsed fraction into an interpolated fraction + * and then into an animated value (from the evaluator. The function is called mostly during + * animation updates, but it is also called when the <code>end()</code> + * function is called, to set the final value on the property. + * + * <p>Overrides of this method must call the superclass to perform the calculation + * of the animated value.</p> + * + * @param fraction The elapsed fraction of the animation. + */ + void animateValue(float fraction) { + fraction = mInterpolator.getInterpolation(fraction); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].calculateValue(fraction); + } + if (mUpdateListeners != null) { + int numListeners = mUpdateListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mUpdateListeners.get(i).onAnimationUpdate(this); + } + } + } + + @Override + public ValueAnimator clone() { + final ValueAnimator anim = (ValueAnimator) super.clone(); + if (mUpdateListeners != null) { + ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners; + anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(); + int numListeners = oldListeners.size(); + for (int i = 0; i < numListeners; ++i) { + anim.mUpdateListeners.add(oldListeners.get(i)); + } + } + anim.mSeekTime = -1; + anim.mPlayingBackwards = false; + anim.mCurrentIteration = 0; + anim.mInitialized = false; + anim.mPlayingState = STOPPED; + anim.mStartedDelay = false; + PropertyValuesHolder[] oldValues = mValues; + if (oldValues != null) { + int numValues = oldValues.length; + anim.mValues = new PropertyValuesHolder[numValues]; + for (int i = 0; i < numValues; ++i) { + anim.mValues[i] = oldValues[i].clone(); + } + anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues); + for (int i = 0; i < numValues; ++i) { + PropertyValuesHolder valuesHolder = mValues[i]; + anim.mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); + } + } + return anim; + } + + /** + * Implementors of this interface can add themselves as update listeners + * to an <code>ValueAnimator</code> instance to receive callbacks on every animation + * frame, after the current frame's values have been calculated for that + * <code>ValueAnimator</code>. + */ + public static interface AnimatorUpdateListener { + /** + * <p>Notifies the occurrence of another frame of the animation.</p> + * + * @param animation The animation which was repeated. + */ + void onAnimationUpdate(ValueAnimator animation); + + } +}
\ No newline at end of file diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 56cf399..16d105a 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -16,7 +16,7 @@ package android.app; -import android.animation.Animatable; +import android.animation.Animator; import android.content.ComponentCallbacks; import android.content.Context; import android.content.Intent; @@ -26,7 +26,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.util.AndroidRuntimeException; import android.util.AttributeSet; -import android.util.Log; import android.util.SparseArray; import android.view.ContextMenu; import android.view.LayoutInflater; @@ -755,7 +754,7 @@ public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener /** * Called when a fragment loads an animation. */ - public Animatable onCreateAnimatable(int transit, boolean enter, int nextAnim) { + public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { return null; } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 7641f61..4d4f892 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -16,10 +16,10 @@ package android.app; -import android.animation.Animatable; -import android.animation.AnimatableInflater; -import android.animation.PropertyAnimator; -import android.animation.Sequencer; +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.content.res.TypedArray; import android.os.Bundle; import android.os.Handler; @@ -248,16 +248,16 @@ final class FragmentManagerImpl implements FragmentManager { return f; } - Animatable loadAnimatable(Fragment fragment, int transit, boolean enter, + Animator loadAnimator(Fragment fragment, int transit, boolean enter, int transitionStyle) { - Animatable animObj = fragment.onCreateAnimatable(transit, enter, + Animator animObj = fragment.onCreateAnimator(transit, enter, fragment.mNextAnim); if (animObj != null) { return animObj; } if (fragment.mNextAnim != 0) { - Animatable anim = AnimatableInflater.loadAnimatable(mActivity, fragment.mNextAnim); + Animator anim = AnimatorInflater.loadAnimator(mActivity, fragment.mNextAnim); if (anim != null) { return anim; } @@ -288,7 +288,7 @@ final class FragmentManagerImpl implements FragmentManager { return null; } - return AnimatableInflater.loadAnimatable(mActivity, anim); + return AnimatorInflater.loadAnimator(mActivity, anim); } void moveToState(Fragment f, int newState, int transit, int transitionStyle) { @@ -360,13 +360,13 @@ final class FragmentManagerImpl implements FragmentManager { if (f.mView != null) { f.mView.setSaveFromParentEnabled(false); if (container != null) { - Animatable anim = loadAnimatable(f, transit, true, + Animator anim = loadAnimator(f, transit, true, transitionStyle); if (anim != null) { - if (anim instanceof Sequencer) { - ((Sequencer)anim).setTarget(f.mView); - } else if (anim instanceof PropertyAnimator) { - ((PropertyAnimator)anim).setTarget(f.mView); + if (anim instanceof AnimatorSet) { + ((AnimatorSet)anim).setTarget(f.mView); + } else if (anim instanceof ObjectAnimator) { + ((ObjectAnimator)anim).setTarget(f.mView); } anim.start(); } @@ -448,13 +448,13 @@ final class FragmentManagerImpl implements FragmentManager { } if (f.mView != null && f.mContainer != null) { if (mCurState > Fragment.INITIALIZING) { - Animatable anim = loadAnimatable(f, transit, true, + Animator anim = loadAnimator(f, transit, true, transitionStyle); if (anim != null) { - if (anim instanceof Sequencer) { - ((Sequencer)anim).setTarget(f.mView); - } else if (anim instanceof PropertyAnimator) { - ((PropertyAnimator)anim).setTarget(f.mView); + if (anim instanceof AnimatorSet) { + ((AnimatorSet)anim).setTarget(f.mView); + } else if (anim instanceof ObjectAnimator) { + ((ObjectAnimator)anim).setTarget(f.mView); } anim.start(); } @@ -588,13 +588,13 @@ final class FragmentManagerImpl implements FragmentManager { if (!fragment.mHidden) { fragment.mHidden = true; if (fragment.mView != null) { - Animatable anim = loadAnimatable(fragment, transition, true, + Animator anim = loadAnimator(fragment, transition, true, transitionStyle); if (anim != null) { - if (anim instanceof Sequencer) { - ((Sequencer)anim).setTarget(fragment.mView); - } else if (anim instanceof PropertyAnimator) { - ((PropertyAnimator)anim).setTarget(fragment.mView); + if (anim instanceof AnimatorSet) { + ((AnimatorSet)anim).setTarget(fragment.mView); + } else if (anim instanceof ObjectAnimator) { + ((ObjectAnimator)anim).setTarget(fragment.mView); } anim.start(); } @@ -612,13 +612,13 @@ final class FragmentManagerImpl implements FragmentManager { if (fragment.mHidden) { fragment.mHidden = false; if (fragment.mView != null) { - Animatable anim = loadAnimatable(fragment, transition, true, + Animator anim = loadAnimator(fragment, transition, true, transitionStyle); if (anim != null) { - if (anim instanceof Sequencer) { - ((Sequencer)anim).setTarget(fragment.mView); - } else if (anim instanceof PropertyAnimator) { - ((PropertyAnimator)anim).setTarget(fragment.mView); + if (anim instanceof AnimatorSet) { + ((AnimatorSet)anim).setTarget(fragment.mView); + } else if (anim instanceof ObjectAnimator) { + ((ObjectAnimator)anim).setTarget(fragment.mView); } anim.start(); } diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java index c090f8e..32ff647 100644 --- a/core/java/android/view/animation/AnimationUtils.java +++ b/core/java/android/view/animation/AnimationUtils.java @@ -35,7 +35,7 @@ import java.io.IOException; public class AnimationUtils { /** - * These flags are used when parsing Sequencer objects + * These flags are used when parsing AnimatorSet objects */ private static final int TOGETHER = 0; private static final int SEQUENTIALLY = 1; diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java index 830e899..e8d96c5 100644 --- a/core/java/android/widget/AdapterViewAnimator.java +++ b/core/java/android/widget/AdapterViewAnimator.java @@ -18,12 +18,10 @@ package android.widget; import java.util.ArrayList; -import android.animation.PropertyAnimator; +import android.animation.ObjectAnimator; import android.content.Context; import android.content.Intent; import android.content.res.TypedArray; -import android.graphics.Rect; -import android.graphics.RectF; import android.os.Handler; import android.os.Looper; import android.os.Parcel; @@ -220,13 +218,13 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter> * @param view The view that is being animated */ void animateViewForTransition(int fromIndex, int toIndex, View view) { - PropertyAnimator pa; + ObjectAnimator pa; if (fromIndex == -1) { view.setAlpha(0.0f); - pa = new PropertyAnimator(400, view, "alpha", 0.0f, 1.0f); + pa = new ObjectAnimator(400, view, "alpha", 0.0f, 1.0f); pa.start(); } else if (toIndex == -1) { - pa = new PropertyAnimator(400, view, "alpha", 1.0f, 0.0f); + pa = new ObjectAnimator(400, view, "alpha", 1.0f, 0.0f); pa.start(); } } diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java index 9025b83..0a97904 100644 --- a/core/java/android/widget/StackView.java +++ b/core/java/android/widget/StackView.java @@ -16,8 +16,8 @@ package android.widget; -import android.animation.PropertyAnimator; import android.animation.PropertyValuesHolder; +import android.animation.ObjectAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BlurMaskFilter; @@ -166,7 +166,7 @@ public class StackView extends AdapterViewAnimator { } view.setVisibility(VISIBLE); - PropertyAnimator<Float> fadeIn = new PropertyAnimator<Float>(DEFAULT_ANIMATION_DURATION, + ObjectAnimator<Float> fadeIn = new ObjectAnimator<Float>(DEFAULT_ANIMATION_DURATION, view, "alpha", view.getAlpha(), 1.0f); fadeIn.start(); } else if (fromIndex == mNumActiveViews - 1 && toIndex == mNumActiveViews - 2) { @@ -181,7 +181,7 @@ public class StackView extends AdapterViewAnimator { new PropertyValuesHolder<Float>("YProgress", 0.0f); PropertyValuesHolder<Float> slideInX = new PropertyValuesHolder<Float>("XProgress", 0.0f); - PropertyAnimator pa = new PropertyAnimator(duration, animationSlider, + ObjectAnimator pa = new ObjectAnimator(duration, animationSlider, slideInX, slideInY); pa.setInterpolator(new LinearInterpolator()); pa.start(); @@ -196,7 +196,7 @@ public class StackView extends AdapterViewAnimator { new PropertyValuesHolder<Float>("YProgress", 1.0f); PropertyValuesHolder<Float> slideOutX = new PropertyValuesHolder<Float>("XProgress", 0.0f); - PropertyAnimator pa = new PropertyAnimator(duration, animationSlider, + ObjectAnimator pa = new ObjectAnimator(duration, animationSlider, slideOutX, slideOutY); pa.setInterpolator(new LinearInterpolator()); pa.start(); @@ -208,7 +208,7 @@ public class StackView extends AdapterViewAnimator { lp.setVerticalOffset(-mViewHeight); } else if (toIndex == -1) { // Fade item out - PropertyAnimator<Float> fadeOut = new PropertyAnimator<Float> + ObjectAnimator<Float> fadeOut = new ObjectAnimator<Float> (DEFAULT_ANIMATION_DURATION, view, "alpha", view.getAlpha(), 0.0f); fadeOut.start(); } @@ -234,7 +234,7 @@ public class StackView extends AdapterViewAnimator { PropertyValuesHolder<Float> translationY = new PropertyValuesHolder<Float>("translationY", transY); - PropertyAnimator pa = new PropertyAnimator(100, view, scaleX, scaleY, translationY); + ObjectAnimator pa = new ObjectAnimator(100, view, scaleX, scaleY, translationY); pa.start(); } } @@ -510,7 +510,7 @@ public class StackView extends AdapterViewAnimator { new PropertyValuesHolder<Float>("YProgress", finalYProgress); PropertyValuesHolder<Float> snapBackX = new PropertyValuesHolder<Float>("XProgress", 0.0f); - PropertyAnimator pa = new PropertyAnimator(duration, animationSlider, + ObjectAnimator pa = new ObjectAnimator(duration, animationSlider, snapBackX, snapBackY); pa.setInterpolator(new LinearInterpolator()); pa.start(); @@ -529,7 +529,7 @@ public class StackView extends AdapterViewAnimator { new PropertyValuesHolder<Float>("YProgress", finalYProgress); PropertyValuesHolder<Float> snapBackX = new PropertyValuesHolder<Float>("XProgress", 0.0f); - PropertyAnimator pa = new PropertyAnimator(duration, animationSlider, + ObjectAnimator pa = new ObjectAnimator(duration, animationSlider, snapBackX, snapBackY); pa.start(); } @@ -870,7 +870,7 @@ public class StackView extends AdapterViewAnimator { private Rect invalidateRect = new Rect(); private RectF invalidateRectf = new RectF(); - // This is public so that PropertyAnimator can access it + // This is public so that ObjectAnimator can access it public void setVerticalOffset(int newVerticalOffset) { int offsetDelta = newVerticalOffset - verticalOffset; verticalOffset = newVerticalOffset; |