summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2010-09-07 13:20:00 -0700
committerChet Haase <chet@google.com>2010-09-08 09:41:21 -0700
commita18a86b43e40e3c15dcca0ae0148d641be9b25fe (patch)
tree80f115b33fa69994f3cf7347d77c3463d1eda439 /core/java/android
parent789a47488c0e834eb80fe6b596dcc3e0ba7f1344 (diff)
downloadframeworks_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')
-rw-r--r--core/java/android/animation/Animatable.java248
-rw-r--r--[-rwxr-xr-x]core/java/android/animation/Animator.java969
-rw-r--r--core/java/android/animation/AnimatorInflater.java (renamed from core/java/android/animation/AnimatableInflater.java)56
-rw-r--r--core/java/android/animation/AnimatorListenerAdapter.java (renamed from core/java/android/animation/AnimatableListenerAdapter.java)14
-rw-r--r--core/java/android/animation/AnimatorSet.java (renamed from core/java/android/animation/Sequencer.java)332
-rw-r--r--core/java/android/animation/Keyframe.java6
-rw-r--r--core/java/android/animation/KeyframeSet.java2
-rw-r--r--core/java/android/animation/LayoutTransition.java104
-rw-r--r--core/java/android/animation/ObjectAnimator.java (renamed from core/java/android/animation/PropertyAnimator.java)22
-rw-r--r--core/java/android/animation/PropertyValuesHolder.java50
-rw-r--r--core/java/android/animation/TypeEvaluator.java4
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java972
-rw-r--r--core/java/android/app/Fragment.java5
-rw-r--r--core/java/android/app/FragmentManager.java56
-rw-r--r--core/java/android/view/animation/AnimationUtils.java2
-rw-r--r--core/java/android/widget/AdapterViewAnimator.java10
-rw-r--r--core/java/android/widget/StackView.java18
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;