summaryrefslogtreecommitdiffstats
path: root/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation
diff options
context:
space:
mode:
Diffstat (limited to 'actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation')
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java278
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java54
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java1111
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java42
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java136
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java42
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java135
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java361
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java227
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java491
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java1012
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java44
-rw-r--r--actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java1265
13 files changed, 0 insertions, 5198 deletions
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java
deleted file mode 100644
index 2caf5b4a9..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Animator.java
+++ /dev/null
@@ -1,278 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import java.util.ArrayList;
-
-import android.view.animation.Interpolator;
-
-/**
- * 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 abstract class Animator implements Cloneable {
-
-
- /**
- * The set of listeners to be sent events through the life of an animation.
- */
- ArrayList<AnimatorListener> mListeners = null;
-
- /**
- * Starts this animation. If the animation has a nonzero startDelay, the animation will start
- * running after that delay elapses. A non-delayed animation will have its initial
- * value(s) set immediately, followed by calls to
- * {@link AnimatorListener#onAnimationStart(Animator)} for any listeners of this animator.
- *
- * <p>The animation started by calling this method will be run on the thread that called
- * this method. This thread should have a Looper on it (a runtime exception will be thrown if
- * this is not the case). Also, if the animation will animate
- * properties of objects in the view hierarchy, then the calling thread should be the UI
- * thread for that view hierarchy.</p>
- *
- */
- public void start() {
- }
-
- /**
- * 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.
- *
- * <p>This method must be called on the thread that is running the animation.</p>
- */
- public void cancel() {
- }
-
- /**
- * 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.
- *
- * <p>This method must be called on the thread that is running the animation.</p>
- */
- 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 Animator 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(/*Time*/Interpolator value);
-
- /**
- * Returns whether this Animator is currently running (having been started and gone past any
- * initial startDelay period and not yet ended).
- *
- * @return Whether the Animator is running.
- */
- public abstract boolean isRunning();
-
- /**
- * Returns whether this Animator has been started and not yet ended. This state is a superset
- * of the state of {@link #isRunning()}, because an Animator with a nonzero
- * {@link #getStartDelay() startDelay} will return true for {@link #isStarted()} during the
- * delay phase, whereas {@link #isRunning()} will return true only after the delay phase
- * is complete.
- *
- * @return Whether the Animator has been started and not yet ended.
- */
- public boolean isStarted() {
- // Default method returns value for isRunning(). Subclasses should override to return a
- // real value.
- return 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(AnimatorListener listener) {
- if (mListeners == null) {
- mListeners = new ArrayList<AnimatorListener>();
- }
- 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(AnimatorListener listener) {
- if (mListeners == null) {
- return;
- }
- mListeners.remove(listener);
- if (mListeners.size() == 0) {
- mListeners = null;
- }
- }
-
- /**
- * Gets the set of {@link android.animation.Animator.AnimatorListener} objects that are currently
- * listening for events on this <code>Animator</code> object.
- *
- * @return ArrayList<AnimatorListener> The set of listeners.
- */
- public ArrayList<AnimatorListener> 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 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));
- }
- }
- 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 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 setupStartValues() {
- }
-
- /**
- * 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.
- */
- 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 ValueAnimator}, 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 AnimatorListener {
- /**
- * <p>Notifies the start of the animation.</p>
- *
- * @param animation The started animation.
- */
- void onAnimationStart(Animator 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(Animator 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(Animator animation);
-
- /**
- * <p>Notifies the repetition of the animation.</p>
- *
- * @param animation The animation which was repeated.
- */
- void onAnimationRepeat(Animator animation);
- }
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java
deleted file mode 100644
index 02ddff48d..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorListenerAdapter.java
+++ /dev/null
@@ -1,54 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-/**
- * 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 AnimatorListenerAdapter implements Animator.AnimatorListener {
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAnimationCancel(Animator animation) {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAnimationEnd(Animator animation) {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void onAnimationStart(Animator animation) {
- }
-
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java
deleted file mode 100644
index 3231080c4..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/AnimatorSet.java
+++ /dev/null
@@ -1,1111 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-import android.view.animation.Interpolator;
-
-/**
- * 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>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>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.
- */
-@SuppressWarnings("unchecked")
-public final class AnimatorSet extends Animator {
-
- /**
- * 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.
- */
-
- /**
- * Tracks animations currently being played, so that we know what to
- * cancel or end when cancel() or end() is called on this AnimatorSet
- */
- private ArrayList<Animator> mPlayingSet = new ArrayList<Animator>();
-
- /**
- * 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<Animator, Node> mNodeMap = new HashMap<Animator, Node>();
-
- /**
- * 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>();
-
- /**
- * The sorted list of nodes. This is the order in which the animations will
- * be played. The details about when exactly they will be played depend
- * on the dependency relationships of the nodes.
- */
- private ArrayList<Node> mSortedNodes = new ArrayList<Node>();
-
- /**
- * Flag indicating whether the nodes should be sorted prior to playing. This
- * flag allows us to cache the previous sorted nodes so that if the sequence
- * is replayed with no changes, it does not have to re-sort the nodes again.
- */
- private boolean mNeedsSort = true;
-
- private AnimatorSetListener mSetListener = null;
-
- /**
- * Flag indicating that the AnimatorSet has been manually
- * terminated (by calling cancel() or end()).
- * This flag is used to avoid starting other animations when currently-playing
- * child animations of this AnimatorSet end. It also determines whether cancel/end
- * notifications are sent out via the normal AnimatorSetListener mechanism.
- */
- boolean mTerminated = false;
-
- /**
- * Indicates whether an AnimatorSet has been start()'d, whether or
- * not there is a nonzero startDelay.
- */
- private boolean mStarted = false;
-
- // The amount of time in ms to delay starting the animation after start() is called
- private long mStartDelay = 0;
-
- // Animator used for a nonzero startDelay
- private ValueAnimator mDelayAnim = null;
-
-
- // 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 AnimatorSet. When a real duration is
- // set, it is passed along to the child animations.
- private long mDuration = -1;
-
-
- /**
- * Sets up this AnimatorSet to play all of the supplied animations at the same time.
- *
- * @param items The animations that will be started simultaneously.
- */
- public void playTogether(Animator... items) {
- if (items != null) {
- mNeedsSort = true;
- Builder builder = play(items[0]);
- for (int i = 1; i < items.length; ++i) {
- builder.with(items[i]);
- }
- }
- }
-
- /**
- * Sets up this AnimatorSet to play all of the supplied animations at the same time.
- *
- * @param items The animations that will be started simultaneously.
- */
- public void playTogether(Collection<Animator> items) {
- if (items != null && items.size() > 0) {
- mNeedsSort = true;
- Builder builder = null;
- for (Animator anim : items) {
- if (builder == null) {
- builder = play(anim);
- } else {
- builder.with(anim);
- }
- }
- }
- }
-
- /**
- * Sets up this AnimatorSet to play each of the supplied animations when the
- * previous animation ends.
- *
- * @param items The animations that will be started one after another.
- */
- public void playSequentially(Animator... items) {
- if (items != null) {
- mNeedsSort = true;
- if (items.length == 1) {
- play(items[0]);
- } else {
- for (int i = 0; i < items.length - 1; ++i) {
- play(items[i]).before(items[i+1]);
- }
- }
- }
- }
-
- /**
- * Sets up this AnimatorSet to play each of the supplied animations when the
- * previous animation ends.
- *
- * @param items The animations that will be started one after another.
- */
- public void playSequentially(List<Animator> items) {
- if (items != null && items.size() > 0) {
- mNeedsSort = true;
- if (items.size() == 1) {
- play(items.get(0));
- } else {
- for (int i = 0; i < items.size() - 1; ++i) {
- play(items.get(i)).before(items.get(i+1));
- }
- }
- }
- }
-
- /**
- * 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<Animator> The list of child animations of this AnimatorSet.
- */
- public ArrayList<Animator> getChildAnimations() {
- ArrayList<Animator> childList = new ArrayList<Animator>();
- for (Node node : mNodes) {
- childList.add(node.animation);
- }
- return childList;
- }
-
- /**
- * Sets the target object for all current {@link #getChildAnimations() child animations}
- * 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) {
- Animator animation = node.animation;
- if (animation instanceof AnimatorSet) {
- ((AnimatorSet)animation).setTarget(target);
- } else if (animation instanceof ObjectAnimator) {
- ((ObjectAnimator)animation).setTarget(target);
- }
- }
- }
-
- /**
- * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations}
- * of this AnimatorSet.
- *
- * @param interpolator the interpolator to be used by each child animation of this AnimatorSet
- */
- @Override
- public void setInterpolator(/*Time*/Interpolator interpolator) {
- for (Node node : mNodes) {
- node.animation.setInterpolator(interpolator);
- }
- }
-
- /**
- * This method creates a <code>Builder</code> object, which is used to
- * 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 AnimatorSet to play
- * <code>a1</code> and <code>a2</code> at the same time,
- * <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 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
- * <code>Builder</code> the animation upon which the dependency is created,
- * so successive calls to the various functions in <code>Builder</code>
- * will all refer to the initial parameter supplied in <code>play()</code>
- * as the dependency of the other animations. For example, calling
- * <code>play(a1).before(a2).before(a3)</code> will play both <code>a2</code>
- * and <code>a3</code> when a1 ends; it does not set up a dependency between
- * <code>a2</code> and <code>a3</code>.</p>
- *
- * @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 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(Animator anim) {
- if (anim != null) {
- mNeedsSort = true;
- return new Builder(anim);
- }
- return null;
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>Note that canceling a <code>AnimatorSet</code> also cancels all of the animations that it
- * is responsible for.</p>
- */
- @Override
- public void cancel() {
- mTerminated = true;
- if (isStarted()) {
- ArrayList<AnimatorListener> tmpListeners = null;
- if (mListeners != null) {
- tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
- }
- }
- if (mDelayAnim != null && mDelayAnim.isRunning()) {
- // If we're currently in the startDelay period, just cancel that animator and
- // send out the end event to all listeners
- mDelayAnim.cancel();
- } else if (mSortedNodes.size() > 0) {
- for (Node node : mSortedNodes) {
- node.animation.cancel();
- }
- }
- if (tmpListeners != null) {
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationEnd(this);
- }
- }
- mStarted = false;
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * <p>Note that ending a <code>AnimatorSet</code> also ends all of the animations that it is
- * responsible for.</p>
- */
- @Override
- public void end() {
- mTerminated = true;
- if (isStarted()) {
- if (mSortedNodes.size() != mNodes.size()) {
- // hasn't been started yet - sort the nodes now, then end them
- sortNodes();
- for (Node node : mSortedNodes) {
- if (mSetListener == null) {
- mSetListener = new AnimatorSetListener(this);
- }
- node.animation.addListener(mSetListener);
- }
- }
- if (mDelayAnim != null) {
- mDelayAnim.cancel();
- }
- if (mSortedNodes.size() > 0) {
- for (Node node : mSortedNodes) {
- node.animation.end();
- }
- }
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationEnd(this);
- }
- }
- mStarted = false;
- }
- }
-
- /**
- * Returns true if any of the child animations of this AnimatorSet have been started and have
- * not yet ended.
- * @return Whether this AnimatorSet has been started and has not yet ended.
- */
- @Override
- public boolean isRunning() {
- for (Node node : mNodes) {
- if (node.animation.isRunning()) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public boolean isStarted() {
- return mStarted;
- }
-
- /**
- * 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
- */
- @Override
- 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
- */
- @Override
- public void setStartDelay(long startDelay) {
- mStartDelay = startDelay;
- }
-
- /**
- * 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 AnimatorSet.
- */
- @Override
- public long getDuration() {
- return mDuration;
- }
-
- /**
- * 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 AnimatorSet.
- */
- @Override
- public AnimatorSet setDuration(long duration) {
- if (duration < 0) {
- 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 AnimatorSet to
- // insert "play-after" delays
- node.animation.setDuration(duration);
- }
- mDuration = duration;
- return this;
- }
-
- @Override
- public void setupStartValues() {
- for (Node node : mNodes) {
- node.animation.setupStartValues();
- }
- }
-
- @Override
- public void setupEndValues() {
- for (Node node : mNodes) {
- node.animation.setupEndValues();
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * <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.
- */
- @Override
- public void start() {
- mTerminated = false;
- mStarted = true;
-
- // First, sort the nodes (if necessary). This will ensure that sortedNodes
- // contains the animation nodes in the correct order.
- sortNodes();
-
- int numSortedNodes = mSortedNodes.size();
- for (int i = 0; i < numSortedNodes; ++i) {
- Node node = mSortedNodes.get(i);
- // First, clear out the old listeners
- ArrayList<AnimatorListener> oldListeners = node.animation.getListeners();
- if (oldListeners != null && oldListeners.size() > 0) {
- final ArrayList<AnimatorListener> clonedListeners = new
- ArrayList<AnimatorListener>(oldListeners);
-
- for (AnimatorListener listener : clonedListeners) {
- if (listener instanceof DependencyListener ||
- listener instanceof AnimatorSetListener) {
- node.animation.removeListener(listener);
- }
- }
- }
- }
-
- // nodesToStart holds the list of nodes to be started immediately. We don't want to
- // start the animations in the loop directly because we first need to set up
- // dependencies on all of the nodes. For example, we don't want to start an animation
- // when some other animation also wants to start when the first animation begins.
- final ArrayList<Node> nodesToStart = new ArrayList<Node>();
- for (int i = 0; i < numSortedNodes; ++i) {
- Node node = mSortedNodes.get(i);
- if (mSetListener == null) {
- mSetListener = new AnimatorSetListener(this);
- }
- if (node.dependencies == null || node.dependencies.size() == 0) {
- nodesToStart.add(node);
- } else {
- int numDependencies = node.dependencies.size();
- for (int j = 0; j < numDependencies; ++j) {
- Dependency dependency = node.dependencies.get(j);
- dependency.node.animation.addListener(
- new DependencyListener(this, node, dependency.rule));
- }
- node.tmpDependencies = (ArrayList<Dependency>) node.dependencies.clone();
- }
- node.animation.addListener(mSetListener);
- }
- // Now that all dependencies are set up, start the animations that should be started.
- if (mStartDelay <= 0) {
- for (Node node : nodesToStart) {
- node.animation.start();
- mPlayingSet.add(node.animation);
- }
- } else {
- mDelayAnim = ValueAnimator.ofFloat(0f, 1f);
- mDelayAnim.setDuration(mStartDelay);
- mDelayAnim.addListener(new AnimatorListenerAdapter() {
- boolean canceled = false;
- public void onAnimationCancel(Animator anim) {
- canceled = true;
- }
- public void onAnimationEnd(Animator anim) {
- if (!canceled) {
- int numNodes = nodesToStart.size();
- for (int i = 0; i < numNodes; ++i) {
- Node node = nodesToStart.get(i);
- node.animation.start();
- mPlayingSet.add(node.animation);
- }
- }
- }
- });
- mDelayAnim.start();
- }
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationStart(this);
- }
- }
- if (mNodes.size() == 0 && mStartDelay == 0) {
- // Handle unusual case where empty AnimatorSet is started - should send out
- // end event immediately since the event will not be sent out at all otherwise
- mStarted = false;
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this);
- }
- }
- }
- }
-
- @Override
- public AnimatorSet clone() {
- final AnimatorSet anim = (AnimatorSet) super.clone();
- /*
- * The basic clone() operation copies all items. This doesn't work very well for
- * 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,
- * and will populate any appropriate lists, when it is started.
- */
- anim.mNeedsSort = true;
- anim.mTerminated = false;
- anim.mStarted = false;
- 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 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) {
- Node nodeClone = node.clone();
- nodeCloneMap.put(node, nodeClone);
- anim.mNodes.add(nodeClone);
- anim.mNodeMap.put(nodeClone.animation, nodeClone);
- // Clear out the dependencies in the clone; we'll set these up manually later
- nodeClone.dependencies = null;
- nodeClone.tmpDependencies = null;
- nodeClone.nodeDependents = null;
- nodeClone.nodeDependencies = null;
- // clear out any listeners that were set up by the AnimatorSet; these will
- // be set up when the clone's nodes are sorted
- ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners();
- if (cloneListeners != null) {
- ArrayList<AnimatorListener> listenersToRemove = null;
- for (AnimatorListener listener : cloneListeners) {
- if (listener instanceof AnimatorSetListener) {
- if (listenersToRemove == null) {
- listenersToRemove = new ArrayList<AnimatorListener>();
- }
- listenersToRemove.add(listener);
- }
- }
- if (listenersToRemove != null) {
- for (AnimatorListener listener : listenersToRemove) {
- cloneListeners.remove(listener);
- }
- }
- }
- }
- // Now that we've cloned all of the nodes, we're ready to walk through their
- // dependencies, mapping the old dependencies to the new nodes
- for (Node node : mNodes) {
- Node nodeClone = nodeCloneMap.get(node);
- if (node.dependencies != null) {
- for (Dependency dependency : node.dependencies) {
- Node clonedDependencyNode = nodeCloneMap.get(dependency.node);
- Dependency cloneDependency = new Dependency(clonedDependencyNode,
- dependency.rule);
- nodeClone.addDependency(cloneDependency);
- }
- }
- }
-
- return anim;
- }
-
- /**
- * This class is the mechanism by which animations are started based on events in other
- * 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 AnimatorListener {
-
- private AnimatorSet mAnimatorSet;
-
- // The node upon which the dependency is based.
- private Node mNode;
-
- // The Dependency rule (WITH or AFTER) that the listener should wait for on
- // the node
- private int mRule;
-
- public DependencyListener(AnimatorSet animatorSet, Node node, int rule) {
- this.mAnimatorSet = animatorSet;
- this.mNode = node;
- this.mRule = rule;
- }
-
- /**
- * Ignore cancel events for now. We may want to handle this eventually,
- * to prevent follow-on animations from running when some dependency
- * animation is canceled.
- */
- public void onAnimationCancel(Animator animation) {
- }
-
- /**
- * An end event is received - see if this is an event we are listening for
- */
- public void onAnimationEnd(Animator animation) {
- if (mRule == Dependency.AFTER) {
- startIfReady(animation);
- }
- }
-
- /**
- * Ignore repeat events for now
- */
- public void onAnimationRepeat(Animator animation) {
- }
-
- /**
- * A start event is received - see if this is an event we are listening for
- */
- public void onAnimationStart(Animator animation) {
- if (mRule == Dependency.WITH) {
- startIfReady(animation);
- }
- }
-
- /**
- * Check whether the event received is one that the node was waiting for.
- * If so, mark it as complete and see whether it's time to start
- * the animation.
- * @param dependencyAnimation the animation that sent the event.
- */
- private void startIfReady(Animator dependencyAnimation) {
- if (mAnimatorSet.mTerminated) {
- // if the parent AnimatorSet was canceled, then don't start any dependent anims
- return;
- }
- Dependency dependencyToRemove = null;
- int numDependencies = mNode.tmpDependencies.size();
- for (int i = 0; i < numDependencies; ++i) {
- Dependency dependency = mNode.tmpDependencies.get(i);
- if (dependency.rule == mRule &&
- dependency.node.animation == dependencyAnimation) {
- // rule fired - remove the dependency and listener and check to
- // see whether it's time to start the animation
- dependencyToRemove = dependency;
- dependencyAnimation.removeListener(this);
- break;
- }
- }
- mNode.tmpDependencies.remove(dependencyToRemove);
- if (mNode.tmpDependencies.size() == 0) {
- // all dependencies satisfied: start the animation
- mNode.animation.start();
- mAnimatorSet.mPlayingSet.add(mNode.animation);
- }
- }
-
- }
-
- private class AnimatorSetListener implements AnimatorListener {
-
- private AnimatorSet mAnimatorSet;
-
- AnimatorSetListener(AnimatorSet animatorSet) {
- mAnimatorSet = animatorSet;
- }
-
- public void onAnimationCancel(Animator animation) {
- if (!mTerminated) {
- // Listeners are already notified of the AnimatorSet canceling in cancel().
- // The logic below only kicks in when animations end normally
- if (mPlayingSet.size() == 0) {
- if (mListeners != null) {
- int numListeners = mListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mListeners.get(i).onAnimationCancel(mAnimatorSet);
- }
- }
- }
- }
- }
-
- public void onAnimationEnd(Animator animation) {
- animation.removeListener(this);
- mPlayingSet.remove(animation);
- Node animNode = mAnimatorSet.mNodeMap.get(animation);
- animNode.done = true;
- if (!mTerminated) {
- // Listeners are already notified of the AnimatorSet ending in cancel() or
- // end(); the logic below only kicks in when animations end normally
- ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes;
- boolean allDone = true;
- int numSortedNodes = sortedNodes.size();
- for (int i = 0; i < numSortedNodes; ++i) {
- if (!sortedNodes.get(i).done) {
- allDone = false;
- break;
- }
- }
- if (allDone) {
- // If this was the last child animation to end, then notify listeners that this
- // AnimatorSet has ended
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(mAnimatorSet);
- }
- }
- mAnimatorSet.mStarted = false;
- }
- }
- }
-
- // Nothing to do
- public void onAnimationRepeat(Animator animation) {
- }
-
- // Nothing to do
- public void onAnimationStart(Animator animation) {
- }
-
- }
-
- /**
- * This method sorts the current set of nodes, if needed. The sort is a simple
- * DependencyGraph sort, which goes like this:
- * - All nodes without dependencies become 'roots'
- * - while roots list is not null
- * - for each root r
- * - add r to sorted list
- * - remove r as a dependency from any other node
- * - any nodes with no dependencies are added to the roots list
- */
- private void sortNodes() {
- if (mNeedsSort) {
- mSortedNodes.clear();
- ArrayList<Node> roots = new ArrayList<Node>();
- int numNodes = mNodes.size();
- for (int i = 0; i < numNodes; ++i) {
- Node node = mNodes.get(i);
- if (node.dependencies == null || node.dependencies.size() == 0) {
- roots.add(node);
- }
- }
- ArrayList<Node> tmpRoots = new ArrayList<Node>();
- while (roots.size() > 0) {
- int numRoots = roots.size();
- for (int i = 0; i < numRoots; ++i) {
- Node root = roots.get(i);
- mSortedNodes.add(root);
- if (root.nodeDependents != null) {
- int numDependents = root.nodeDependents.size();
- for (int j = 0; j < numDependents; ++j) {
- Node node = root.nodeDependents.get(j);
- node.nodeDependencies.remove(root);
- if (node.nodeDependencies.size() == 0) {
- tmpRoots.add(node);
- }
- }
- }
- }
- roots.clear();
- roots.addAll(tmpRoots);
- tmpRoots.clear();
- }
- mNeedsSort = false;
- if (mSortedNodes.size() != mNodes.size()) {
- throw new IllegalStateException("Circular dependencies cannot exist"
- + " in AnimatorSet");
- }
- } else {
- // Doesn't need sorting, but still need to add in the nodeDependencies list
- // because these get removed as the event listeners fire and the dependencies
- // are satisfied
- int numNodes = mNodes.size();
- for (int i = 0; i < numNodes; ++i) {
- Node node = mNodes.get(i);
- if (node.dependencies != null && node.dependencies.size() > 0) {
- int numDependencies = node.dependencies.size();
- for (int j = 0; j < numDependencies; ++j) {
- Dependency dependency = node.dependencies.get(j);
- if (node.nodeDependencies == null) {
- node.nodeDependencies = new ArrayList<Node>();
- }
- if (!node.nodeDependencies.contains(dependency.node)) {
- node.nodeDependencies.add(dependency.node);
- }
- }
- }
- // nodes are 'done' by default; they become un-done when started, and done
- // again when ended
- node.done = false;
- }
- }
- }
-
- /**
- * Dependency holds information about the node that some other node is
- * dependent upon and the nature of that dependency.
- *
- */
- private static class Dependency {
- static final int WITH = 0; // dependent node must start with this dependency node
- static final int AFTER = 1; // dependent node must start when this dependency node finishes
-
- // The node that the other node with this Dependency is dependent upon
- public Node node;
-
- // The nature of the dependency (WITH or AFTER)
- public int rule;
-
- public Dependency(Node node, int rule) {
- this.node = node;
- this.rule = rule;
- }
- }
-
- /**
- * 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 Animator animation;
-
- /**
- * These are the dependencies that this node's animation has on other
- * nodes. For example, if this node's animation should begin with some
- * other animation ends, then there will be an item in this node's
- * dependencies list for that other animation's node.
- */
- public ArrayList<Dependency> dependencies = null;
-
- /**
- * tmpDependencies is a runtime detail. We use the dependencies list for sorting.
- * 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 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;
-
- /**
- * nodeDependencies is just a list of the nodes that this Node is dependent upon.
- * This information is used in sortNodes(), to determine when a node is a root.
- */
- public ArrayList<Node> nodeDependencies = null;
-
- /**
- * nodeDepdendents is the list of nodes that have this node as a dependency. This
- * is a utility field used in sortNodes to facilitate removing this node as a
- * dependency when it is a root node.
- */
- public ArrayList<Node> nodeDependents = null;
-
- /**
- * Flag indicating whether the animation in this node is finished. This flag
- * 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;
-
- /**
- * Constructs the Node with the animation that it encapsulates. A Node has no
- * dependencies by default; dependencies are added via the addDependency()
- * method.
- *
- * @param animation The animation that the Node encapsulates.
- */
- public Node(Animator animation) {
- this.animation = animation;
- }
-
- /**
- * Add a dependency to this Node. The dependency includes information about the
- * node that this node is dependency upon and the nature of the dependency.
- * @param dependency
- */
- public void addDependency(Dependency dependency) {
- if (dependencies == null) {
- dependencies = new ArrayList<Dependency>();
- nodeDependencies = new ArrayList<Node>();
- }
- dependencies.add(dependency);
- if (!nodeDependencies.contains(dependency.node)) {
- nodeDependencies.add(dependency.node);
- }
- Node dependencyNode = dependency.node;
- if (dependencyNode.nodeDependents == null) {
- dependencyNode.nodeDependents = new ArrayList<Node>();
- }
- dependencyNode.nodeDependents.add(this);
- }
-
- @Override
- public Node clone() {
- try {
- Node node = (Node) super.clone();
- node.animation = animation.clone();
- return node;
- } catch (CloneNotSupportedException e) {
- throw new AssertionError();
- }
- }
- }
-
- /**
- * The <code>Builder</code> object is a utility class to facilitate adding animations to a
- * <code>AnimatorSet</code> along with the relationships between the various animations. The
- * intention of the <code>Builder</code> methods, along with the {@link
- * 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 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 AnimatorSet#play(Animator)}.</p>
- * <p/>
- * <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>
- * 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(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 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>
- * 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>
- * AnimatorSet s = new AnimatorSet();
- * s.play(anim1).before(anim2);
- * s.play(anim2).before(anim3);
- * </pre>
- * <p/>
- * <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 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 AnimatorSet and passed into the constructor of Builder.
- */
- private Node mCurrentNode;
-
- /**
- * 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(Animator anim) {
- mCurrentNode = mNodeMap.get(anim);
- if (mCurrentNode == null) {
- mCurrentNode = new Node(anim);
- mNodeMap.put(anim, mCurrentNode);
- mNodes.add(mCurrentNode);
- }
- }
-
- /**
- * Sets up the given animation to play at the same time as the animation supplied in the
- * {@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 AnimatorSet#play(Animator)} method starts.
- */
- public Builder with(Animator anim) {
- Node node = mNodeMap.get(anim);
- if (node == null) {
- node = new Node(anim);
- mNodeMap.put(anim, node);
- mNodes.add(node);
- }
- Dependency dependency = new Dependency(mCurrentNode, Dependency.WITH);
- node.addDependency(dependency);
- return this;
- }
-
- /**
- * Sets up the given animation to play when the animation supplied in the
- * {@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 AnimatorSet#play(Animator)} method ends.
- */
- public Builder before(Animator anim) {
- Node node = mNodeMap.get(anim);
- if (node == null) {
- node = new Node(anim);
- mNodeMap.put(anim, node);
- mNodes.add(node);
- }
- Dependency dependency = new Dependency(mCurrentNode, Dependency.AFTER);
- node.addDependency(dependency);
- return this;
- }
-
- /**
- * Sets up the given animation to play when the animation supplied in the
- * {@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 AnimatorSet#play(Animator)} method to play.
- */
- public Builder after(Animator anim) {
- Node node = mNodeMap.get(anim);
- if (node == null) {
- node = new Node(anim);
- mNodeMap.put(anim, node);
- mNodes.add(node);
- }
- Dependency dependency = new Dependency(node, Dependency.AFTER);
- mCurrentNode.addDependency(dependency);
- return this;
- }
-
- /**
- * Sets up the animation supplied in the
- * {@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 Builder after(long delay) {
- // setup dummy ValueAnimator just to run the clock
- ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
- anim.setDuration(delay);
- after(anim);
- return this;
- }
-
- }
-
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java
deleted file mode 100644
index e41019364..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatEvaluator.java
+++ /dev/null
@@ -1,42 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-/**
- * This evaluator can be used to perform type interpolation between <code>float</code> values.
- */
-public class FloatEvaluator implements TypeEvaluator<Number> {
-
- /**
- * This function returns the result of linearly interpolating the start and end values, with
- * <code>fraction</code> representing the proportion between the start and end values. The
- * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
- * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
- * and <code>t</code> is <code>fraction</code>.
- *
- * @param fraction The fraction from the starting to the ending values
- * @param startValue The start value; should be of type <code>float</code> or
- * <code>Float</code>
- * @param endValue The end value; should be of type <code>float</code> or <code>Float</code>
- * @return A linear interpolation between the start and end values, given the
- * <code>fraction</code> parameter.
- */
- public Float evaluate(float fraction, Number startValue, Number endValue) {
- float startFloat = startValue.floatValue();
- return startFloat + fraction * (endValue.floatValue() - startFloat);
- }
-} \ No newline at end of file
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java
deleted file mode 100644
index 6d9dafa7a..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/FloatKeyframeSet.java
+++ /dev/null
@@ -1,136 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import java.util.ArrayList;
-import android.view.animation.Interpolator;
-
-import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe;
-
-/**
- * This class holds a collection of FloatKeyframe 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.
- *
- * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for
- * int, exists to speed up the getValue() method when there is no custom
- * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the
- * Object equivalents of these primitive types.</p>
- */
-@SuppressWarnings("unchecked")
-class FloatKeyframeSet extends KeyframeSet {
- private float firstValue;
- private float lastValue;
- private float deltaValue;
- private boolean firstTime = true;
-
- public FloatKeyframeSet(FloatKeyframe... keyframes) {
- super(keyframes);
- }
-
- @Override
- public Object getValue(float fraction) {
- return getFloatValue(fraction);
- }
-
- @Override
- public FloatKeyframeSet clone() {
- ArrayList<Keyframe> keyframes = mKeyframes;
- int numKeyframes = mKeyframes.size();
- FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes];
- for (int i = 0; i < numKeyframes; ++i) {
- newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone();
- }
- FloatKeyframeSet newSet = new FloatKeyframeSet(newKeyframes);
- return newSet;
- }
-
- public float getFloatValue(float fraction) {
- if (mNumKeyframes == 2) {
- if (firstTime) {
- firstTime = false;
- firstValue = ((FloatKeyframe) mKeyframes.get(0)).getFloatValue();
- lastValue = ((FloatKeyframe) mKeyframes.get(1)).getFloatValue();
- deltaValue = lastValue - firstValue;
- }
- if (mInterpolator != null) {
- fraction = mInterpolator.getInterpolation(fraction);
- }
- if (mEvaluator == null) {
- return firstValue + fraction * deltaValue;
- } else {
- return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).floatValue();
- }
- }
- if (fraction <= 0f) {
- final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0);
- final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(1);
- float prevValue = prevKeyframe.getFloatValue();
- float nextValue = nextKeyframe.getFloatValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + intervalFraction * (nextValue - prevValue) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- floatValue();
- } else if (fraction >= 1f) {
- final FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 2);
- final FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(mNumKeyframes - 1);
- float prevValue = prevKeyframe.getFloatValue();
- float nextValue = nextKeyframe.getFloatValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + intervalFraction * (nextValue - prevValue) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- floatValue();
- }
- FloatKeyframe prevKeyframe = (FloatKeyframe) mKeyframes.get(0);
- for (int i = 1; i < mNumKeyframes; ++i) {
- FloatKeyframe nextKeyframe = (FloatKeyframe) mKeyframes.get(i);
- if (fraction < nextKeyframe.getFraction()) {
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevKeyframe.getFraction()) /
- (nextKeyframe.getFraction() - prevKeyframe.getFraction());
- float prevValue = prevKeyframe.getFloatValue();
- float nextValue = nextKeyframe.getFloatValue();
- return mEvaluator == null ?
- prevValue + intervalFraction * (nextValue - prevValue) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- floatValue();
- }
- prevKeyframe = nextKeyframe;
- }
- // shouldn't get here
- return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).floatValue();
- }
-
-}
-
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java
deleted file mode 100644
index ed5e79ec6..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntEvaluator.java
+++ /dev/null
@@ -1,42 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-/**
- * This evaluator can be used to perform type interpolation between <code>int</code> values.
- */
-public class IntEvaluator implements TypeEvaluator<Integer> {
-
- /**
- * This function returns the result of linearly interpolating the start and end values, with
- * <code>fraction</code> representing the proportion between the start and end values. The
- * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
- * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
- * and <code>t</code> is <code>fraction</code>.
- *
- * @param fraction The fraction from the starting to the ending values
- * @param startValue The start value; should be of type <code>int</code> or
- * <code>Integer</code>
- * @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>
- * @return A linear interpolation between the start and end values, given the
- * <code>fraction</code> parameter.
- */
- public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
- int startInt = startValue;
- return (int)(startInt + fraction * (endValue - startInt));
- }
-} \ No newline at end of file
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java
deleted file mode 100644
index e9215e7f8..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/IntKeyframeSet.java
+++ /dev/null
@@ -1,135 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import java.util.ArrayList;
-import android.view.animation.Interpolator;
-
-import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe;
-
-/**
- * This class holds a collection of IntKeyframe 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.
- *
- * <p>This type-specific subclass of KeyframeSet, along with the other type-specific subclass for
- * float, exists to speed up the getValue() method when there is no custom
- * TypeEvaluator set for the animation, so that values can be calculated without autoboxing to the
- * Object equivalents of these primitive types.</p>
- */
-@SuppressWarnings("unchecked")
-class IntKeyframeSet extends KeyframeSet {
- private int firstValue;
- private int lastValue;
- private int deltaValue;
- private boolean firstTime = true;
-
- public IntKeyframeSet(IntKeyframe... keyframes) {
- super(keyframes);
- }
-
- @Override
- public Object getValue(float fraction) {
- return getIntValue(fraction);
- }
-
- @Override
- public IntKeyframeSet clone() {
- ArrayList<Keyframe> keyframes = mKeyframes;
- int numKeyframes = mKeyframes.size();
- IntKeyframe[] newKeyframes = new IntKeyframe[numKeyframes];
- for (int i = 0; i < numKeyframes; ++i) {
- newKeyframes[i] = (IntKeyframe) keyframes.get(i).clone();
- }
- IntKeyframeSet newSet = new IntKeyframeSet(newKeyframes);
- return newSet;
- }
-
- public int getIntValue(float fraction) {
- if (mNumKeyframes == 2) {
- if (firstTime) {
- firstTime = false;
- firstValue = ((IntKeyframe) mKeyframes.get(0)).getIntValue();
- lastValue = ((IntKeyframe) mKeyframes.get(1)).getIntValue();
- deltaValue = lastValue - firstValue;
- }
- if (mInterpolator != null) {
- fraction = mInterpolator.getInterpolation(fraction);
- }
- if (mEvaluator == null) {
- return firstValue + (int)(fraction * deltaValue);
- } else {
- return ((Number)mEvaluator.evaluate(fraction, firstValue, lastValue)).intValue();
- }
- }
- if (fraction <= 0f) {
- final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
- final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(1);
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- intValue();
- } else if (fraction >= 1f) {
- final IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 2);
- final IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(mNumKeyframes - 1);
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- float prevFraction = prevKeyframe.getFraction();
- float nextFraction = nextKeyframe.getFraction();
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction);
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).intValue();
- }
- IntKeyframe prevKeyframe = (IntKeyframe) mKeyframes.get(0);
- for (int i = 1; i < mNumKeyframes; ++i) {
- IntKeyframe nextKeyframe = (IntKeyframe) mKeyframes.get(i);
- if (fraction < nextKeyframe.getFraction()) {
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- float intervalFraction = (fraction - prevKeyframe.getFraction()) /
- (nextKeyframe.getFraction() - prevKeyframe.getFraction());
- int prevValue = prevKeyframe.getIntValue();
- int nextValue = nextKeyframe.getIntValue();
- return mEvaluator == null ?
- prevValue + (int)(intervalFraction * (nextValue - prevValue)) :
- ((Number)mEvaluator.evaluate(intervalFraction, prevValue, nextValue)).
- intValue();
- }
- prevKeyframe = nextKeyframe;
- }
- // shouldn't get here
- return ((Number)mKeyframes.get(mNumKeyframes - 1).getValue()).intValue();
- }
-
-}
-
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java
deleted file mode 100644
index ab76fa7f6..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/Keyframe.java
+++ /dev/null
@@ -1,361 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import android.view.animation.Interpolator;
-
-/**
- * This class holds a time/value pair for an animation. The Keyframe class is used
- * 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 optional {@link TimeInterpolator}
- * object, which defines the time interpolation over the intervalue preceding the keyframe.
- *
- * <p>The Keyframe class itself is abstract. The type-specific factory methods will return
- * a subclass of Keyframe specific to the type of value being stored. This is done to improve
- * performance when dealing with the most common cases (e.g., <code>float</code> and
- * <code>int</code> values). Other types will fall into a more general Keyframe class that
- * treats its values as Objects. Unless your animation requires dealing with a custom type
- * or a data structure that needs to be animated directly (and evaluated using an implementation
- * of {@link TypeEvaluator}), you should stick to using float and int as animations using those
- * types have lower runtime overhead than other types.</p>
- */
-@SuppressWarnings("rawtypes")
-public abstract class Keyframe implements Cloneable {
- /**
- * The time at which mValue will hold true.
- */
- float mFraction;
-
- /**
- * The type of the value in this Keyframe. This type is determined at construction time,
- * based on the type of the <code>value</code> object passed into the constructor.
- */
- Class mValueType;
-
- /**
- * The optional time interpolator for the interval preceding this keyframe. A null interpolator
- * (the default) results in linear interpolation over the interval.
- */
- private /*Time*/Interpolator mInterpolator = null;
-
- /**
- * Flag to indicate whether this keyframe has a valid value. This flag is used when an
- * animation first starts, to populate placeholder keyframes with real values derived
- * from the target object.
- */
- boolean mHasValue = false;
-
- /**
- * Constructs a Keyframe object with the given time and value. The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
- */
- public static Keyframe ofInt(float fraction, int value) {
- return new IntKeyframe(fraction, value);
- }
-
- /**
- * Constructs a Keyframe object with the given time. The value at this time will be derived
- * from the target object when the animation first starts (note that this implies that keyframes
- * with no initial value must be used as part of an {@link ObjectAnimator}).
- * The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- */
- public static Keyframe ofInt(float fraction) {
- return new IntKeyframe(fraction);
- }
-
- /**
- * Constructs a Keyframe object with the given time and value. The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
- */
- public static Keyframe ofFloat(float fraction, float value) {
- return new FloatKeyframe(fraction, value);
- }
-
- /**
- * Constructs a Keyframe object with the given time. The value at this time will be derived
- * from the target object when the animation first starts (note that this implies that keyframes
- * with no initial value must be used as part of an {@link ObjectAnimator}).
- * The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- */
- public static Keyframe ofFloat(float fraction) {
- return new FloatKeyframe(fraction);
- }
-
- /**
- * Constructs a Keyframe object with the given time and value. The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- * @param value The value that the object will animate to as the animation time approaches
- * the time in this keyframe, and the the value animated from as the time passes the time in
- * this keyframe.
- */
- public static Keyframe ofObject(float fraction, Object value) {
- return new ObjectKeyframe(fraction, value);
- }
-
- /**
- * Constructs a Keyframe object with the given time. The value at this time will be derived
- * from the target object when the animation first starts (note that this implies that keyframes
- * with no initial value must be used as part of an {@link ObjectAnimator}).
- * The time defines the
- * time, as a proportion of an overall animation's duration, at which the value will hold true
- * for the animation. The value for the animation between keyframes will be calculated as
- * an interpolation between the values at those keyframes.
- *
- * @param fraction The time, expressed as a value between 0 and 1, representing the fraction
- * of time elapsed of the overall animation duration.
- */
- public static Keyframe ofObject(float fraction) {
- return new ObjectKeyframe(fraction, null);
- }
-
- /**
- * Indicates whether this keyframe has a valid value. This method is called internally when
- * an {@link ObjectAnimator} first starts; keyframes without values are assigned values at
- * that time by deriving the value for the property from the target object.
- *
- * @return boolean Whether this object has a value assigned.
- */
- public boolean hasValue() {
- return mHasValue;
- }
-
- /**
- * Gets the value for this Keyframe.
- *
- * @return The value for this Keyframe.
- */
- public abstract Object getValue();
-
- /**
- * Sets the value for this Keyframe.
- *
- * @param value value for this Keyframe.
- */
- public abstract void setValue(Object value);
-
- /**
- * Gets the time for this keyframe, as a fraction of the overall animation duration.
- *
- * @return The time associated with this keyframe, as a fraction of the overall animation
- * duration. This should be a value between 0 and 1.
- */
- public float getFraction() {
- return mFraction;
- }
-
- /**
- * Sets the time for this keyframe, as a fraction of the overall animation duration.
- *
- * @param fraction time associated with this keyframe, as a fraction of the overall animation
- * duration. This should be a value between 0 and 1.
- */
- public void setFraction(float fraction) {
- mFraction = fraction;
- }
-
- /**
- * Gets the optional interpolator for this Keyframe. A value of <code>null</code> indicates
- * that there is no interpolation, which is the same as linear interpolation.
- *
- * @return The optional interpolator for this Keyframe.
- */
- public /*Time*/Interpolator getInterpolator() {
- return mInterpolator;
- }
-
- /**
- * Sets the optional interpolator for this Keyframe. A value of <code>null</code> indicates
- * that there is no interpolation, which is the same as linear interpolation.
- *
- * @return The optional interpolator for this Keyframe.
- */
- public void setInterpolator(/*Time*/Interpolator interpolator) {
- mInterpolator = interpolator;
- }
-
- /**
- * 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.
- *
- * @return The type of the value stored in the Keyframe.
- */
- public Class getType() {
- return mValueType;
- }
-
- @Override
- public abstract Keyframe clone();
-
- /**
- * This internal subclass is used for all types which are not int or float.
- */
- static class ObjectKeyframe extends Keyframe {
-
- /**
- * The value of the animation at the time mFraction.
- */
- Object mValue;
-
- ObjectKeyframe(float fraction, Object value) {
- mFraction = fraction;
- mValue = value;
- mHasValue = (value != null);
- mValueType = mHasValue ? value.getClass() : Object.class;
- }
-
- public Object getValue() {
- return mValue;
- }
-
- public void setValue(Object value) {
- mValue = value;
- mHasValue = (value != null);
- }
-
- @Override
- public ObjectKeyframe clone() {
- ObjectKeyframe kfClone = new ObjectKeyframe(getFraction(), mValue);
- kfClone.setInterpolator(getInterpolator());
- return kfClone;
- }
- }
-
- /**
- * Internal subclass used when the keyframe value is of type int.
- */
- static class IntKeyframe extends Keyframe {
-
- /**
- * The value of the animation at the time mFraction.
- */
- int mValue;
-
- IntKeyframe(float fraction, int value) {
- mFraction = fraction;
- mValue = value;
- mValueType = int.class;
- mHasValue = true;
- }
-
- IntKeyframe(float fraction) {
- mFraction = fraction;
- mValueType = int.class;
- }
-
- public int getIntValue() {
- return mValue;
- }
-
- public Object getValue() {
- return mValue;
- }
-
- public void setValue(Object value) {
- if (value != null && value.getClass() == Integer.class) {
- mValue = ((Integer)value).intValue();
- mHasValue = true;
- }
- }
-
- @Override
- public IntKeyframe clone() {
- IntKeyframe kfClone = new IntKeyframe(getFraction(), mValue);
- kfClone.setInterpolator(getInterpolator());
- return kfClone;
- }
- }
-
- /**
- * Internal subclass used when the keyframe value is of type float.
- */
- static class FloatKeyframe extends Keyframe {
- /**
- * The value of the animation at the time mFraction.
- */
- float mValue;
-
- FloatKeyframe(float fraction, float value) {
- mFraction = fraction;
- mValue = value;
- mValueType = float.class;
- mHasValue = true;
- }
-
- FloatKeyframe(float fraction) {
- mFraction = fraction;
- mValueType = float.class;
- }
-
- public float getFloatValue() {
- return mValue;
- }
-
- public Object getValue() {
- return mValue;
- }
-
- public void setValue(Object value) {
- if (value != null && value.getClass() == Float.class) {
- mValue = ((Float)value).floatValue();
- mHasValue = true;
- }
- }
-
- @Override
- public FloatKeyframe clone() {
- FloatKeyframe kfClone = new FloatKeyframe(getFraction(), mValue);
- kfClone.setInterpolator(getInterpolator());
- return kfClone;
- }
- }
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java
deleted file mode 100644
index a71e1ad3c..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/KeyframeSet.java
+++ /dev/null
@@ -1,227 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import android.view.animation.Interpolator;
-
-import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.FloatKeyframe;
-import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.IntKeyframe;
-import com.actionbarsherlock.internal.nineoldandroids.animation.Keyframe.ObjectKeyframe;
-
-/**
- * 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.
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-class KeyframeSet {
-
- int mNumKeyframes;
-
- Keyframe mFirstKeyframe;
- Keyframe mLastKeyframe;
- /*Time*/Interpolator mInterpolator; // only used in the 2-keyframe case
- ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes
- TypeEvaluator mEvaluator;
-
-
- public KeyframeSet(Keyframe... keyframes) {
- mNumKeyframes = keyframes.length;
- mKeyframes = new ArrayList<Keyframe>();
- mKeyframes.addAll(Arrays.asList(keyframes));
- mFirstKeyframe = mKeyframes.get(0);
- mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
- mInterpolator = mLastKeyframe.getInterpolator();
- }
-
- public static KeyframeSet ofInt(int... values) {
- int numKeyframes = values.length;
- IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)];
- if (numKeyframes == 1) {
- keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f);
- keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]);
- } else {
- keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) {
- keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new IntKeyframeSet(keyframes);
- }
-
- public static KeyframeSet ofFloat(float... values) {
- int numKeyframes = values.length;
- FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)];
- if (numKeyframes == 1) {
- keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f);
- keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]);
- } else {
- keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) {
- keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new FloatKeyframeSet(keyframes);
- }
-
- public static KeyframeSet ofKeyframe(Keyframe... keyframes) {
- // if all keyframes of same primitive type, create the appropriate KeyframeSet
- int numKeyframes = keyframes.length;
- boolean hasFloat = false;
- boolean hasInt = false;
- boolean hasOther = false;
- for (int i = 0; i < numKeyframes; ++i) {
- if (keyframes[i] instanceof FloatKeyframe) {
- hasFloat = true;
- } else if (keyframes[i] instanceof IntKeyframe) {
- hasInt = true;
- } else {
- hasOther = true;
- }
- }
- if (hasFloat && !hasInt && !hasOther) {
- FloatKeyframe floatKeyframes[] = new FloatKeyframe[numKeyframes];
- for (int i = 0; i < numKeyframes; ++i) {
- floatKeyframes[i] = (FloatKeyframe) keyframes[i];
- }
- return new FloatKeyframeSet(floatKeyframes);
- } else if (hasInt && !hasFloat && !hasOther) {
- IntKeyframe intKeyframes[] = new IntKeyframe[numKeyframes];
- for (int i = 0; i < numKeyframes; ++i) {
- intKeyframes[i] = (IntKeyframe) keyframes[i];
- }
- return new IntKeyframeSet(intKeyframes);
- } else {
- return new KeyframeSet(keyframes);
- }
- }
-
- public static KeyframeSet ofObject(Object... values) {
- int numKeyframes = values.length;
- ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)];
- if (numKeyframes == 1) {
- keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f);
- keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]);
- } else {
- keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]);
- for (int i = 1; i < numKeyframes; ++i) {
- keyframes[i] = (ObjectKeyframe) Keyframe.ofObject((float) i / (numKeyframes - 1), values[i]);
- }
- }
- return new KeyframeSet(keyframes);
- }
-
- /**
- * Sets the TypeEvaluator to be used when calculating animated values. This object
- * is required only for KeyframeSets that are not either IntKeyframeSet or FloatKeyframeSet,
- * both of which assume their own evaluator to speed up calculations with those primitive
- * types.
- *
- * @param evaluator The TypeEvaluator to be used to calculate animated values.
- */
- public void setEvaluator(TypeEvaluator evaluator) {
- mEvaluator = evaluator;
- }
-
- @Override
- public KeyframeSet clone() {
- ArrayList<Keyframe> keyframes = mKeyframes;
- int numKeyframes = mKeyframes.size();
- Keyframe[] newKeyframes = new Keyframe[numKeyframes];
- for (int i = 0; i < numKeyframes; ++i) {
- newKeyframes[i] = keyframes.get(i).clone();
- }
- KeyframeSet newSet = new KeyframeSet(newKeyframes);
- return newSet;
- }
-
- /**
- * Gets the animated value, given the elapsed fraction of the animation (interpolated by the
- * animation's interpolator) and the evaluator used to calculate in-between values. This
- * function maps the input fraction to the appropriate keyframe interval and a fraction
- * between them and returns the interpolated value. Note that the input fraction may fall
- * outside the [0-1] bounds, if the animation's interpolator made that happen (e.g., a
- * spring interpolation that might send the fraction past 1.0). We handle this situation by
- * just using the two keyframes at the appropriate end when the value is outside those bounds.
- *
- * @param fraction The elapsed fraction of the animation
- * @return The animated value.
- */
- public Object getValue(float fraction) {
-
- // Special-case optimization for the common case of only two keyframes
- if (mNumKeyframes == 2) {
- if (mInterpolator != null) {
- fraction = mInterpolator.getInterpolation(fraction);
- }
- return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(),
- mLastKeyframe.getValue());
- }
- if (fraction <= 0f) {
- final Keyframe nextKeyframe = mKeyframes.get(1);
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- final float prevFraction = mFirstKeyframe.getFraction();
- float intervalFraction = (fraction - prevFraction) /
- (nextKeyframe.getFraction() - prevFraction);
- return mEvaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(),
- nextKeyframe.getValue());
- } else if (fraction >= 1f) {
- final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2);
- final /*Time*/Interpolator interpolator = mLastKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- final float prevFraction = prevKeyframe.getFraction();
- float intervalFraction = (fraction - prevFraction) /
- (mLastKeyframe.getFraction() - prevFraction);
- return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
- mLastKeyframe.getValue());
- }
- Keyframe prevKeyframe = mFirstKeyframe;
- for (int i = 1; i < mNumKeyframes; ++i) {
- Keyframe nextKeyframe = mKeyframes.get(i);
- if (fraction < nextKeyframe.getFraction()) {
- final /*Time*/Interpolator interpolator = nextKeyframe.getInterpolator();
- if (interpolator != null) {
- fraction = interpolator.getInterpolation(fraction);
- }
- final float prevFraction = prevKeyframe.getFraction();
- float intervalFraction = (fraction - prevFraction) /
- (nextKeyframe.getFraction() - prevFraction);
- return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(),
- nextKeyframe.getValue());
- }
- prevKeyframe = nextKeyframe;
- }
- // shouldn't reach here
- return mLastKeyframe.getValue();
- }
-
- @Override
- public String toString() {
- String returnVal = " ";
- for (int i = 0; i < mNumKeyframes; ++i) {
- returnVal += mKeyframes.get(i).getValue() + " ";
- }
- return returnVal;
- }
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java
deleted file mode 100644
index 21d15c02a..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ObjectAnimator.java
+++ /dev/null
@@ -1,491 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import android.util.Log;
-//import android.util.Property;
-
-//import java.lang.reflect.Method;
-import java.util.ArrayList;
-
-/**
- * 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.
- *
- * @see #setPropertyName(String)
- *
- */
-@SuppressWarnings("rawtypes")
-public final class ObjectAnimator extends ValueAnimator {
- private static final boolean DBG = false;
-
- // The target object on which the property exists, set in the constructor
- private Object mTarget;
-
- private String mPropertyName;
-
- //private Property mProperty;
-
- /**
- * Sets the name of the property that will be animated. This name is used to derive
- * a setter function that will be called to set animated values.
- * For example, a property name of <code>foo</code> will result
- * in a call to the function <code>setFoo()</code> on the target object. If either
- * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
- * also be derived and called.
- *
- * <p>For best performance of the mechanism that calls the setter function determined by the
- * name of the property being animated, use <code>float</code> or <code>int</code> typed values,
- * and make the setter function for those properties have a <code>void</code> return value. This
- * will cause the code to take an optimized path for these constrained circumstances. Other
- * property types and return types will work, but will have more overhead in processing
- * the requests due to normal reflection mechanisms.</p>
- *
- * <p>Note that the setter function derived from this property name
- * must take the same parameter type as the
- * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
- * the setter function will fail.</p>
- *
- * <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>
- *
- * @param propertyName The name of the property being animated. Should not be null.
- */
- public void setPropertyName(String propertyName) {
- // mValues could be null if this is being constructed piecemeal. Just record the
- // propertyName to be used later when setValues() is called if so.
- if (mValues != null) {
- PropertyValuesHolder valuesHolder = mValues[0];
- String oldName = valuesHolder.getPropertyName();
- valuesHolder.setPropertyName(propertyName);
- mValuesMap.remove(oldName);
- mValuesMap.put(propertyName, valuesHolder);
- }
- mPropertyName = propertyName;
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
-
- /**
- * Sets the property that will be animated. Property objects will take precedence over
- * properties specified by the {@link #setPropertyName(String)} method. Animations should
- * be set up to use one or the other, not both.
- *
- * @param property The property being animated. Should not be null.
- */
- //public void setProperty(Property property) {
- // // mValues could be null if this is being constructed piecemeal. Just record the
- // // propertyName to be used later when setValues() is called if so.
- // if (mValues != null) {
- // PropertyValuesHolder valuesHolder = mValues[0];
- // String oldName = valuesHolder.getPropertyName();
- // valuesHolder.setProperty(property);
- // mValuesMap.remove(oldName);
- // mValuesMap.put(mPropertyName, valuesHolder);
- // }
- // if (mProperty != null) {
- // mPropertyName = property.getName();
- // }
- // mProperty = property;
- // // New property/values/target should cause re-initialization prior to starting
- // mInitialized = false;
- //}
-
- /**
- * Gets the name of the property that will be animated. This name will be used to derive
- * a setter function that will be called to set animated values.
- * For example, a property name of <code>foo</code> will result
- * in a call to the function <code>setFoo()</code> on the target object. If either
- * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
- * also be derived and called.
- */
- public String getPropertyName() {
- return mPropertyName;
- }
-
- /**
- * Creates a new ObjectAnimator object. This default constructor is primarily for
- * use internally; the other constructors which take parameters are more generally
- * useful.
- */
- public ObjectAnimator() {
- }
-
- /**
- * Private utility constructor that initializes the target object and name of the
- * property being animated.
- *
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
- * @param propertyName The name of the property being animated.
- */
- private ObjectAnimator(Object target, String propertyName) {
- mTarget = target;
- setPropertyName(propertyName);
- }
-
- /**
- * Private utility constructor that initializes the target object and property being animated.
- *
- * @param target The object whose property is to be animated.
- * @param property The property being animated.
- */
- //private <T> ObjectAnimator(T target, Property<T, ?> property) {
- // mTarget = target;
- // setProperty(property);
- //}
-
- /**
- * Constructs and returns an ObjectAnimator that animates between int values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
- * @param propertyName The name of the property being animated.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- public static ObjectAnimator ofInt(Object target, String propertyName, int... values) {
- ObjectAnimator anim = new ObjectAnimator(target, propertyName);
- anim.setIntValues(values);
- return anim;
- }
-
- /**
- * Constructs and returns an ObjectAnimator that animates between int values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated.
- * @param property The property being animated.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- //public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> property, int... values) {
- // ObjectAnimator anim = new ObjectAnimator(target, property);
- // anim.setIntValues(values);
- // return anim;
- //}
-
- /**
- * Constructs and returns an ObjectAnimator that animates between float values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
- * @param propertyName The name of the property being animated.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
- ObjectAnimator anim = new ObjectAnimator(target, propertyName);
- anim.setFloatValues(values);
- return anim;
- }
-
- /**
- * Constructs and returns an ObjectAnimator that animates between float values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated.
- * @param property The property being animated.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- //public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> property,
- // float... values) {
- // ObjectAnimator anim = new ObjectAnimator(target, property);
- // anim.setFloatValues(values);
- // return anim;
- //}
-
- /**
- * Constructs and returns an ObjectAnimator that animates between Object values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated. This object should
- * have a public method on it called <code>setName()</code>, where <code>name</code> is
- * the value of the <code>propertyName</code> parameter.
- * @param propertyName The name of the property being animated.
- * @param evaluator A TypeEvaluator that will be called on each animation frame to
- * provide the necessary interpolation between the Object values to derive the animated
- * value.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- public static ObjectAnimator ofObject(Object target, String propertyName,
- TypeEvaluator evaluator, Object... values) {
- ObjectAnimator anim = new ObjectAnimator(target, propertyName);
- anim.setObjectValues(values);
- anim.setEvaluator(evaluator);
- return anim;
- }
-
- /**
- * Constructs and returns an ObjectAnimator that animates between Object values. A single
- * value implies that that value is the one being animated to. Two values imply a starting
- * and ending values. More than two values imply a starting value, values to animate through
- * along the way, and an ending value (these values will be distributed evenly across
- * the duration of the animation).
- *
- * @param target The object whose property is to be animated.
- * @param property The property being animated.
- * @param evaluator A TypeEvaluator that will be called on each animation frame to
- * provide the necessary interpolation between the Object values to derive the animated
- * value.
- * @param values A set of values that the animation will animate between over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- //public static <T, V> ObjectAnimator ofObject(T target, Property<T, V> property,
- // TypeEvaluator<V> evaluator, V... values) {
- // ObjectAnimator anim = new ObjectAnimator(target, property);
- // anim.setObjectValues(values);
- // anim.setEvaluator(evaluator);
- // return anim;
- //}
-
- /**
- * Constructs and returns an ObjectAnimator that animates between the sets of values specified
- * in <code>PropertyValueHolder</code> objects. This variant should 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.
- *
- * @param target The object whose property is to be animated. Depending on how the
- * PropertyValuesObjects were constructed, the target object should either have the {@link
- * android.util.Property} objects used to construct the PropertyValuesHolder objects or (if the
- * PropertyValuesHOlder objects were created with property names) the target object should have
- * public methods on it called <code>setName()</code>, where <code>name</code> is the name of
- * the property passed in as the <code>propertyName</code> parameter for each of the
- * PropertyValuesHolder objects.
- * @param values A set of PropertyValuesHolder objects whose values will be animated between
- * over time.
- * @return An ObjectAnimator object that is set up to animate between the given values.
- */
- public static ObjectAnimator ofPropertyValuesHolder(Object target,
- PropertyValuesHolder... values) {
- ObjectAnimator anim = new ObjectAnimator();
- anim.mTarget = target;
- anim.setValues(values);
- return anim;
- }
-
- @Override
- public void setIntValues(int... values) {
- if (mValues == null || mValues.length == 0) {
- // No values yet - this animator is being constructed piecemeal. Init the values with
- // whatever the current propertyName is
- //if (mProperty != null) {
- // setValues(PropertyValuesHolder.ofInt(mProperty, values));
- //} else {
- setValues(PropertyValuesHolder.ofInt(mPropertyName, values));
- //}
- } else {
- super.setIntValues(values);
- }
- }
-
- @Override
- public void setFloatValues(float... values) {
- if (mValues == null || mValues.length == 0) {
- // No values yet - this animator is being constructed piecemeal. Init the values with
- // whatever the current propertyName is
- //if (mProperty != null) {
- // setValues(PropertyValuesHolder.ofFloat(mProperty, values));
- //} else {
- setValues(PropertyValuesHolder.ofFloat(mPropertyName, values));
- //}
- } else {
- super.setFloatValues(values);
- }
- }
-
- @Override
- public void setObjectValues(Object... values) {
- if (mValues == null || mValues.length == 0) {
- // No values yet - this animator is being constructed piecemeal. Init the values with
- // whatever the current propertyName is
- //if (mProperty != null) {
- // setValues(PropertyValuesHolder.ofObject(mProperty, (TypeEvaluator)null, values));
- //} else {
- setValues(PropertyValuesHolder.ofObject(mPropertyName, (TypeEvaluator)null, values));
- //}
- } else {
- super.setObjectValues(values);
- }
- }
-
- @Override
- public void start() {
- if (DBG) {
- Log.d("ObjectAnimator", "Anim target, duration: " + mTarget + ", " + getDuration());
- for (int i = 0; i < mValues.length; ++i) {
- PropertyValuesHolder pvh = mValues[i];
- ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
- Log.d("ObjectAnimator", " Values[" + i + "]: " +
- pvh.getPropertyName() + ", " + keyframes.get(0).getValue() + ", " +
- keyframes.get(pvh.mKeyframeSet.mNumKeyframes - 1).getValue());
- }
- }
- super.start();
- }
-
- /**
- * 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. This includes setting mEvaluator, if the user has not yet
- * set it up, and the setter/getter methods, if the user did not supply
- * them.
- *
- * <p>Overriders of this method should call the superclass method to cause
- * internal mechanisms to be set up correctly.</p>
- */
- @Override
- void initAnimation() {
- if (!mInitialized) {
- // mValueType may change due to setter/getter setup; do this before calling super.init(),
- // which uses mValueType to set up the default type evaluator.
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].setupSetterAndGetter(mTarget);
- }
- super.initAnimation();
- }
- }
-
- /**
- * Sets the length of the animation. The default duration is 300 milliseconds.
- *
- * @param duration The length of the animation, in milliseconds.
- * @return ObjectAnimator The object called with setDuration(). This return
- * value makes it easier to compose statements together that construct and then set the
- * duration, as in
- * <code>ObjectAnimator.ofInt(target, propertyName, 0, 10).setDuration(500).start()</code>.
- */
- @Override
- public ObjectAnimator setDuration(long duration) {
- super.setDuration(duration);
- return this;
- }
-
-
- /**
- * The target object whose property will be animated by this animation
- *
- * @return The object being animated
- */
- public Object getTarget() {
- return mTarget;
- }
-
- /**
- * Sets the target object whose property will be animated by this animation
- *
- * @param target The object being animated
- */
- @Override
- public void setTarget(Object target) {
- if (mTarget != target) {
- final Object oldTarget = mTarget;
- mTarget = target;
- if (oldTarget != null && target != null && oldTarget.getClass() == target.getClass()) {
- return;
- }
- // New target type should cause re-initialization prior to starting
- mInitialized = false;
- }
- }
-
- @Override
- public void setupStartValues() {
- initAnimation();
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].setupStartValue(mTarget);
- }
- }
-
- @Override
- public void setupEndValues() {
- initAnimation();
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].setupEndValue(mTarget);
- }
- }
-
- /**
- * 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.
- */
- @Override
- void animateValue(float fraction) {
- super.animateValue(fraction);
- int numValues = mValues.length;
- for (int i = 0; i < numValues; ++i) {
- mValues[i].setAnimatedValue(mTarget);
- }
- }
-
- @Override
- public ObjectAnimator clone() {
- final ObjectAnimator anim = (ObjectAnimator) super.clone();
- return anim;
- }
-
- @Override
- public String toString() {
- String returnVal = "ObjectAnimator@" + Integer.toHexString(hashCode()) + ", target " +
- mTarget;
- if (mValues != null) {
- for (int i = 0; i < mValues.length; ++i) {
- returnVal += "\n " + mValues[i].toString();
- }
- }
- return returnVal;
- }
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java
deleted file mode 100644
index 84f7504ab..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/PropertyValuesHolder.java
+++ /dev/null
@@ -1,1012 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-//import android.util.FloatProperty;
-//import android.util.IntProperty;
-import android.util.Log;
-//import android.util.Property;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-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 ValueAnimator or ObjectAnimator that operate on several different properties
- * in parallel.
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class PropertyValuesHolder 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 ObjectAnimator. But this is the name by which
- * aniamted values are looked up with getAnimatedValue(String) in ValueAnimator.
- */
- String mPropertyName;
-
- /**
- * @hide
- */
- //protected Property mProperty;
-
- /**
- * The setter function, if needed. ObjectAnimator hands off this functionality to
- * PropertyValuesHolder, since it holds all of the per-property information. This
- * property is automatically
- * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator.
- */
- Method mSetter = null;
-
- /**
- * The getter function, if needed. ObjectAnimator hands off this functionality to
- * PropertyValuesHolder, since it holds all of the per-property information. This
- * property is automatically
- * 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;
-
- /**
- * The type of values supplied. This information is used both in deriving the setter/getter
- * functions and in deriving the type of TypeEvaluator.
- */
- Class mValueType;
-
- /**
- * The set of keyframes (time/value pairs) that define this animation.
- */
- KeyframeSet mKeyframeSet = null;
-
-
- // type evaluators for the primitive types handled by this implementation
- private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
- private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
-
- // We try several different types when searching for appropriate setter/getter functions.
- // The caller may have supplied values in a type that does not match the setter/getter
- // functions (such as the integers 0 and 1 to represent floating point values for alpha).
- // Also, the use of generics in constructors means that we end up with the Object versions
- // of primitive types (Float vs. float). But most likely, the setter/getter functions
- // will take primitive types instead.
- // So we supply an ordered array of other types to try before giving up.
- private static Class[] FLOAT_VARIANTS = {float.class, Float.class, double.class, int.class,
- Double.class, Integer.class};
- private static Class[] INTEGER_VARIANTS = {int.class, Integer.class, float.class, double.class,
- Float.class, Double.class};
- private static Class[] DOUBLE_VARIANTS = {double.class, Double.class, float.class, int.class,
- Float.class, Integer.class};
-
- // These maps hold all property entries for a particular class. This map
- // is used to speed up property/setter/getter lookups for a given class/property
- // combination. No need to use reflection on the combination more than once.
- private static final HashMap<Class, HashMap<String, Method>> sSetterPropertyMap =
- new HashMap<Class, HashMap<String, Method>>();
- private static final HashMap<Class, HashMap<String, Method>> sGetterPropertyMap =
- new HashMap<Class, HashMap<String, Method>>();
-
- // This lock is used to ensure that only one thread is accessing the property maps
- // at a time.
- final ReentrantReadWriteLock mPropertyMapLock = new ReentrantReadWriteLock();
-
- // Used to pass single value to varargs parameter in setter invocation
- final Object[] mTmpValueArray = new Object[1];
-
- /**
- * The type evaluator used to calculate the animated values. This evaluator is determined
- * automatically based on the type of the start/end objects passed into the constructor,
- * but the system only knows about the primitive types int and float. Any other
- * type will need to set the evaluator to a custom evaluator for that type.
- */
- private TypeEvaluator mEvaluator;
-
- /**
- * The value most recently calculated by calculateValue(). This is set during
- * that function and might be retrieved later either by ValueAnimator.animatedValue() or
- * by the property-setting logic in ObjectAnimator.animatedValue().
- */
- private Object mAnimatedValue;
-
- /**
- * Internal utility constructor, used by the factory methods to set the property name.
- * @param propertyName The name of the property for this holder.
- */
- private PropertyValuesHolder(String propertyName) {
- mPropertyName = propertyName;
- }
-
- /**
- * Internal utility constructor, used by the factory methods to set the property.
- * @param property The property for this holder.
- */
- //private PropertyValuesHolder(Property property) {
- // mProperty = property;
- // if (property != null) {
- // mPropertyName = property.getName();
- // }
- //}
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property name and
- * set of int values.
- * @param propertyName The name of the property being animated.
- * @param values The values that the named property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- public static PropertyValuesHolder ofInt(String propertyName, int... values) {
- return new IntPropertyValuesHolder(propertyName, values);
- }
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property and
- * set of int values.
- * @param property The property being animated. Should not be null.
- * @param values The values that the property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- //public static PropertyValuesHolder ofInt(Property<?, Integer> property, int... values) {
- // return new IntPropertyValuesHolder(property, values);
- //}
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property name and
- * set of float values.
- * @param propertyName The name of the property being animated.
- * @param values The values that the named property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- public static PropertyValuesHolder ofFloat(String propertyName, float... values) {
- return new FloatPropertyValuesHolder(propertyName, values);
- }
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property and
- * set of float values.
- * @param property The property being animated. Should not be null.
- * @param values The values that the property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- //public static PropertyValuesHolder ofFloat(Property<?, Float> property, float... values) {
- // return new FloatPropertyValuesHolder(property, values);
- //}
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property name and
- * set of Object values. This variant also takes a TypeEvaluator because the system
- * cannot automatically interpolate between objects of unknown type.
- *
- * @param propertyName The name of the property being animated.
- * @param evaluator A TypeEvaluator that will be called on each animation frame to
- * provide the necessary interpolation between the Object values to derive the animated
- * value.
- * @param values The values that the named property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- public static PropertyValuesHolder ofObject(String propertyName, TypeEvaluator evaluator,
- Object... values) {
- PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName);
- pvh.setObjectValues(values);
- pvh.setEvaluator(evaluator);
- return pvh;
- }
-
- /**
- * Constructs and returns a PropertyValuesHolder with a given property and
- * set of Object values. This variant also takes a TypeEvaluator because the system
- * cannot automatically interpolate between objects of unknown type.
- *
- * @param property The property being animated. Should not be null.
- * @param evaluator A TypeEvaluator that will be called on each animation frame to
- * provide the necessary interpolation between the Object values to derive the animated
- * value.
- * @param values The values that the property will animate between.
- * @return PropertyValuesHolder The constructed PropertyValuesHolder object.
- */
- //public static <V> PropertyValuesHolder ofObject(Property property,
- // TypeEvaluator<V> evaluator, V... values) {
- // PropertyValuesHolder pvh = new PropertyValuesHolder(property);
- // pvh.setObjectValues(values);
- // pvh.setEvaluator(evaluator);
- // return pvh;
- //}
-
- /**
- * Constructs and returns a PropertyValuesHolder object with the specified property name and set
- * of values. These values can be of any type, but the type should be consistent so that
- * an appropriate {@link android.animation.TypeEvaluator} can be found that matches
- * the common type.
- * <p>If there is only one value, it is assumed to be the end value of an animation,
- * and an initial value will be derived, if possible, by calling a getter function
- * 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 ObjectAnimator}, and with a getter function
- * derived automatically from <code>propertyName</code>, 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 ObjectAnimator object, or
- * just a name used to get animated values, such as if this object is used with an
- * ValueAnimator object.
- * @param values The set of values to animate between.
- */
- public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) {
- KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values);
- if (keyframeSet instanceof IntKeyframeSet) {
- return new IntPropertyValuesHolder(propertyName, (IntKeyframeSet) keyframeSet);
- } else if (keyframeSet instanceof FloatKeyframeSet) {
- return new FloatPropertyValuesHolder(propertyName, (FloatKeyframeSet) keyframeSet);
- }
- else {
- PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName);
- pvh.mKeyframeSet = keyframeSet;
- pvh.mValueType = values[0].getType();
- return pvh;
- }
- }
-
- /**
- * Constructs and returns a PropertyValuesHolder object with the specified property and set
- * of values. These values can be of any type, but the type should be consistent so that
- * an appropriate {@link android.animation.TypeEvaluator} can be found that matches
- * the common type.
- * <p>If there is only one value, it is assumed to be the end value of an animation,
- * and an initial value will be derived, if possible, by calling the property's
- * {@link android.util.Property#get(Object)} function.
- * 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 with
- * {@link ObjectAnimator}, since otherwise PropertyValuesHolder has
- * no way of determining what the value should be.
- * @param property The property associated with this set of values. Should not be null.
- * @param values The set of values to animate between.
- */
- //public static PropertyValuesHolder ofKeyframe(Property property, Keyframe... values) {
- // KeyframeSet keyframeSet = KeyframeSet.ofKeyframe(values);
- // if (keyframeSet instanceof IntKeyframeSet) {
- // return new IntPropertyValuesHolder(property, (IntKeyframeSet) keyframeSet);
- // } else if (keyframeSet instanceof FloatKeyframeSet) {
- // return new FloatPropertyValuesHolder(property, (FloatKeyframeSet) keyframeSet);
- // }
- // else {
- // PropertyValuesHolder pvh = new PropertyValuesHolder(property);
- // pvh.mKeyframeSet = keyframeSet;
- // pvh.mValueType = ((Keyframe)values[0]).getType();
- // return pvh;
- // }
- //}
-
- /**
- * Set the animated values for this object to this set of ints.
- * If there is only one value, it is assumed to be the end value of an animation,
- * and an initial value will be derived, if possible, by calling a getter function
- * 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 ObjectAnimator}, and with a getter function
- * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
- * no way of determining what the value should be.
- *
- * @param values One or more values that the animation will animate between.
- */
- public void setIntValues(int... values) {
- mValueType = int.class;
- mKeyframeSet = KeyframeSet.ofInt(values);
- }
-
- /**
- * Set the animated values for this object to this set of floats.
- * If there is only one value, it is assumed to be the end value of an animation,
- * and an initial value will be derived, if possible, by calling a getter function
- * 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 ObjectAnimator}, and with a getter function
- * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
- * no way of determining what the value should be.
- *
- * @param values One or more values that the animation will animate between.
- */
- public void setFloatValues(float... values) {
- mValueType = float.class;
- mKeyframeSet = KeyframeSet.ofFloat(values);
- }
-
- /**
- * Set the animated values for this object to this set of Keyframes.
- *
- * @param values One or more values that the animation will animate between.
- */
- public void setKeyframes(Keyframe... values) {
- int numKeyframes = values.length;
- Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)];
- mValueType = values[0].getType();
- for (int i = 0; i < numKeyframes; ++i) {
- keyframes[i] = values[i];
- }
- mKeyframeSet = new KeyframeSet(keyframes);
- }
-
- /**
- * Set the animated values for this object to this set of Objects.
- * If there is only one value, it is assumed to be the end value of an animation,
- * and an initial value will be derived, if possible, by calling a getter function
- * 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 ObjectAnimator}, and with a getter function
- * derived automatically from <code>propertyName</code>, since otherwise PropertyValuesHolder has
- * no way of determining what the value should be.
- *
- * @param values One or more values that the animation will animate between.
- */
- public void setObjectValues(Object... values) {
- mValueType = values[0].getClass();
- mKeyframeSet = KeyframeSet.ofObject(values);
- }
-
- /**
- * Determine the setter or getter function using the JavaBeans convention of setFoo or
- * getFoo for a property named 'foo'. This function figures out what the name of the
- * function should be and uses reflection to find the Method with that name on the
- * target object.
- *
- * @param targetClass The class to search for the method
- * @param prefix "set" or "get", depending on whether we need a setter or getter.
- * @param valueType The type of the parameter (in the case of a setter). This type
- * is derived from the values set on this PropertyValuesHolder. This type is used as
- * a first guess at the parameter type, but we check for methods with several different
- * types to avoid problems with slight mis-matches between supplied values and actual
- * value types used on the setter.
- * @return Method the method associated with mPropertyName.
- */
- private Method getPropertyFunction(Class targetClass, String prefix, Class valueType) {
- // TODO: faster implementation...
- Method returnVal = null;
- String methodName = getMethodName(prefix, mPropertyName);
- Class args[] = null;
- if (valueType == null) {
- try {
- returnVal = targetClass.getMethod(methodName, args);
- } catch (NoSuchMethodException e) {
- Log.e("PropertyValuesHolder", targetClass.getSimpleName() + " - " +
- "Couldn't find no-arg method for property " + mPropertyName + ": " + e);
- }
- } else {
- args = new Class[1];
- Class typeVariants[];
- if (mValueType.equals(Float.class)) {
- typeVariants = FLOAT_VARIANTS;
- } else if (mValueType.equals(Integer.class)) {
- typeVariants = INTEGER_VARIANTS;
- } else if (mValueType.equals(Double.class)) {
- typeVariants = DOUBLE_VARIANTS;
- } else {
- typeVariants = new Class[1];
- typeVariants[0] = mValueType;
- }
- for (Class typeVariant : typeVariants) {
- args[0] = typeVariant;
- try {
- returnVal = targetClass.getMethod(methodName, args);
- // change the value type to suit
- mValueType = typeVariant;
- return returnVal;
- } catch (NoSuchMethodException e) {
- // Swallow the error and keep trying other variants
- }
- }
- // If we got here, then no appropriate function was found
- Log.e("PropertyValuesHolder",
- "Couldn't find " + prefix + "ter property " + mPropertyName +
- " for " + targetClass.getSimpleName() +
- " with value type "+ mValueType);
- }
-
- return returnVal;
- }
-
-
- /**
- * Returns the setter or getter requested. This utility function checks whether the
- * requested method exists in the propertyMapMap cache. If not, it calls another
- * utility function to request the Method from the targetClass directly.
- * @param targetClass The Class on which the requested method should exist.
- * @param propertyMapMap The cache of setters/getters derived so far.
- * @param prefix "set" or "get", for the setter or getter.
- * @param valueType The type of parameter passed into the method (null for getter).
- * @return Method the method associated with mPropertyName.
- */
- private Method setupSetterOrGetter(Class targetClass,
- HashMap<Class, HashMap<String, Method>> propertyMapMap,
- String prefix, Class valueType) {
- Method setterOrGetter = null;
- try {
- // Have to lock property map prior to reading it, to guard against
- // another thread putting something in there after we've checked it
- // but before we've added an entry to it
- mPropertyMapLock.writeLock().lock();
- HashMap<String, Method> propertyMap = propertyMapMap.get(targetClass);
- if (propertyMap != null) {
- setterOrGetter = propertyMap.get(mPropertyName);
- }
- if (setterOrGetter == null) {
- setterOrGetter = getPropertyFunction(targetClass, prefix, valueType);
- if (propertyMap == null) {
- propertyMap = new HashMap<String, Method>();
- propertyMapMap.put(targetClass, propertyMap);
- }
- propertyMap.put(mPropertyName, setterOrGetter);
- }
- } finally {
- mPropertyMapLock.writeLock().unlock();
- }
- return setterOrGetter;
- }
-
- /**
- * Utility function to get the setter from targetClass
- * @param targetClass The Class on which the requested method should exist.
- */
- void setupSetter(Class targetClass) {
- mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", mValueType);
- }
-
- /**
- * Utility function to get the getter from targetClass
- */
- private void setupGetter(Class targetClass) {
- mGetter = setupSetterOrGetter(targetClass, sGetterPropertyMap, "get", null);
- }
-
- /**
- * 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
- * supplied values was null. If there is a null value, then the getter (supplied or derived)
- * will be called to set those null values to the current value of the property
- * on the target object.
- * @param target The object on which the setter (and possibly getter) exist.
- */
- void setupSetterAndGetter(Object target) {
- //if (mProperty != null) {
- // // check to make sure that mProperty is on the class of target
- // try {
- // Object testValue = mProperty.get(target);
- // for (Keyframe kf : mKeyframeSet.mKeyframes) {
- // if (!kf.hasValue()) {
- // kf.setValue(mProperty.get(target));
- // }
- // }
- // return;
- // } catch (ClassCastException e) {
- // Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() +
- // ") on target object " + target + ". Trying reflection instead");
- // mProperty = null;
- // }
- //}
- Class targetClass = target.getClass();
- if (mSetter == null) {
- setupSetter(targetClass);
- }
- for (Keyframe kf : mKeyframeSet.mKeyframes) {
- if (!kf.hasValue()) {
- if (mGetter == null) {
- setupGetter(targetClass);
- }
- try {
- kf.setValue(mGetter.invoke(target));
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
- }
-
- /**
- * Utility function to set the value stored in a particular Keyframe. The value used is
- * whatever the value is for the property name specified in the keyframe on the target object.
- *
- * @param target The target object from which the current value should be extracted.
- * @param kf The keyframe which holds the property name and value.
- */
- private void setupValue(Object target, Keyframe kf) {
- //if (mProperty != null) {
- // kf.setValue(mProperty.get(target));
- //}
- try {
- if (mGetter == null) {
- Class targetClass = target.getClass();
- setupGetter(targetClass);
- }
- kf.setValue(mGetter.invoke(target));
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
-
- /**
- * 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.
- *
- * @param target The object which holds the start values that should be set.
- */
- void setupStartValue(Object target) {
- setupValue(target, mKeyframeSet.mKeyframes.get(0));
- }
-
- /**
- * 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.
- *
- * @param target The object which holds the start values that should be set.
- */
- void setupEndValue(Object target) {
- setupValue(target, mKeyframeSet.mKeyframes.get(mKeyframeSet.mKeyframes.size() - 1));
- }
-
- @Override
- public PropertyValuesHolder clone() {
- try {
- PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone();
- newPVH.mPropertyName = mPropertyName;
- //newPVH.mProperty = mProperty;
- newPVH.mKeyframeSet = mKeyframeSet.clone();
- newPVH.mEvaluator = mEvaluator;
- return newPVH;
- } catch (CloneNotSupportedException e) {
- // won't reach here
- return null;
- }
- }
-
- /**
- * 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 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
- */
- void setAnimatedValue(Object target) {
- //if (mProperty != null) {
- // mProperty.set(target, getAnimatedValue());
- //}
- if (mSetter != null) {
- try {
- mTmpValueArray[0] = getAnimatedValue();
- mSetter.invoke(target, mTmpValueArray);
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
-
- /**
- * Internal function, called by ValueAnimator, to set up the TypeEvaluator that will be used
- * to calculate animated values.
- */
- void init() {
- if (mEvaluator == null) {
- // We already handle int and float automatically, but not their Object
- // equivalents
- mEvaluator = (mValueType == Integer.class) ? sIntEvaluator :
- (mValueType == Float.class) ? sFloatEvaluator :
- null;
- }
- if (mEvaluator != null) {
- // KeyframeSet knows how to evaluate the common types - only give it a custom
- // evaluator if one has been set on this class
- mKeyframeSet.setEvaluator(mEvaluator);
- }
- }
-
- /**
- * The TypeEvaluator will the automatically determined based on the type of values
- * supplied to PropertyValuesHolder. The evaluator can be manually set, however, if so
- * desired. This may be important in cases where either the type of the values supplied
- * do not match the way that they should be interpolated between, or if the values
- * are of a custom type or one not currently understood by the animation system. Currently,
- * only values of type float and int (and their Object equivalents: Float
- * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator.
- * @param evaluator
- */
- public void setEvaluator(TypeEvaluator evaluator) {
- mEvaluator = evaluator;
- mKeyframeSet.setEvaluator(evaluator);
- }
-
- /**
- * Function used to calculate the value according to the evaluator set up for
- * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue().
- *
- * @param fraction The elapsed, interpolated fraction of the animation.
- */
- void calculateValue(float fraction) {
- mAnimatedValue = mKeyframeSet.getValue(fraction);
- }
-
- /**
- * Sets the name of the property that will be animated. This name is used to derive
- * a setter function that will be called to set animated values.
- * For example, a property name of <code>foo</code> will result
- * in a call to the function <code>setFoo()</code> on the target object. If either
- * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
- * also be derived and called.
- *
- * <p>Note that the setter function derived from this property name
- * must take the same parameter type as the
- * <code>valueFrom</code> and <code>valueTo</code> properties, otherwise the call to
- * the setter function will fail.</p>
- *
- * @param propertyName The name of the property being animated.
- */
- public void setPropertyName(String propertyName) {
- mPropertyName = propertyName;
- }
-
- /**
- * Sets the property that will be animated.
- *
- * <p>Note that if this PropertyValuesHolder object is used with ObjectAnimator, the property
- * must exist on the target object specified in that ObjectAnimator.</p>
- *
- * @param property The property being animated.
- */
- //public void setProperty(Property property) {
- // mProperty = property;
- //}
-
- /**
- * Gets the name of the property that will be animated. This name will be used to derive
- * a setter function that will be called to set animated values.
- * For example, a property name of <code>foo</code> will result
- * in a call to the function <code>setFoo()</code> on the target object. If either
- * <code>valueFrom</code> or <code>valueTo</code> is null, then a getter function will
- * also be derived and called.
- */
- public String getPropertyName() {
- return mPropertyName;
- }
-
- /**
- * Internal function, called by ValueAnimator and ObjectAnimator, to retrieve the value
- * most recently calculated in calculateValue().
- * @return
- */
- Object getAnimatedValue() {
- return mAnimatedValue;
- }
-
- @Override
- public String toString() {
- return mPropertyName + ": " + mKeyframeSet.toString();
- }
-
- /**
- * Utility method to derive a setter/getter method name from a property name, where the
- * prefix is typically "set" or "get" and the first letter of the property name is
- * capitalized.
- *
- * @param prefix The precursor to the method name, before the property name begins, typically
- * "set" or "get".
- * @param propertyName The name of the property that represents the bulk of the method name
- * after the prefix. The first letter of this word will be capitalized in the resulting
- * method name.
- * @return String the property name converted to a method name according to the conventions
- * specified above.
- */
- static String getMethodName(String prefix, String propertyName) {
- if (propertyName == null || propertyName.length() == 0) {
- // shouldn't get here
- return prefix;
- }
- char firstLetter = Character.toUpperCase(propertyName.charAt(0));
- String theRest = propertyName.substring(1);
- return prefix + firstLetter + theRest;
- }
-
- static class IntPropertyValuesHolder extends PropertyValuesHolder {
-
- // Cache JNI functions to avoid looking them up twice
- //private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
- // new HashMap<Class, HashMap<String, Integer>>();
- //int mJniSetter;
- //private IntProperty mIntProperty;
-
- IntKeyframeSet mIntKeyframeSet;
- int mIntAnimatedValue;
-
- public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) {
- super(propertyName);
- mValueType = int.class;
- mKeyframeSet = keyframeSet;
- mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
- }
-
- //public IntPropertyValuesHolder(Property property, IntKeyframeSet keyframeSet) {
- // super(property);
- // mValueType = int.class;
- // mKeyframeSet = keyframeSet;
- // mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
- // if (property instanceof IntProperty) {
- // mIntProperty = (IntProperty) mProperty;
- // }
- //}
-
- public IntPropertyValuesHolder(String propertyName, int... values) {
- super(propertyName);
- setIntValues(values);
- }
-
- //public IntPropertyValuesHolder(Property property, int... values) {
- // super(property);
- // setIntValues(values);
- // if (property instanceof IntProperty) {
- // mIntProperty = (IntProperty) mProperty;
- // }
- //}
-
- @Override
- public void setIntValues(int... values) {
- super.setIntValues(values);
- mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet;
- }
-
- @Override
- void calculateValue(float fraction) {
- mIntAnimatedValue = mIntKeyframeSet.getIntValue(fraction);
- }
-
- @Override
- Object getAnimatedValue() {
- return mIntAnimatedValue;
- }
-
- @Override
- public IntPropertyValuesHolder clone() {
- IntPropertyValuesHolder newPVH = (IntPropertyValuesHolder) super.clone();
- newPVH.mIntKeyframeSet = (IntKeyframeSet) newPVH.mKeyframeSet;
- return newPVH;
- }
-
- /**
- * 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 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
- */
- @Override
- void setAnimatedValue(Object target) {
- //if (mIntProperty != null) {
- // mIntProperty.setValue(target, mIntAnimatedValue);
- // return;
- //}
- //if (mProperty != null) {
- // mProperty.set(target, mIntAnimatedValue);
- // return;
- //}
- //if (mJniSetter != 0) {
- // nCallIntMethod(target, mJniSetter, mIntAnimatedValue);
- // return;
- //}
- if (mSetter != null) {
- try {
- mTmpValueArray[0] = mIntAnimatedValue;
- mSetter.invoke(target, mTmpValueArray);
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
-
- @Override
- void setupSetter(Class targetClass) {
- //if (mProperty != null) {
- // return;
- //}
- // Check new static hashmap<propName, int> for setter method
- //try {
- // mPropertyMapLock.writeLock().lock();
- // HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass);
- // if (propertyMap != null) {
- // Integer mJniSetterInteger = propertyMap.get(mPropertyName);
- // if (mJniSetterInteger != null) {
- // mJniSetter = mJniSetterInteger;
- // }
- // }
- // if (mJniSetter == 0) {
- // String methodName = getMethodName("set", mPropertyName);
- // mJniSetter = nGetIntMethod(targetClass, methodName);
- // if (mJniSetter != 0) {
- // if (propertyMap == null) {
- // propertyMap = new HashMap<String, Integer>();
- // sJNISetterPropertyMap.put(targetClass, propertyMap);
- // }
- // propertyMap.put(mPropertyName, mJniSetter);
- // }
- // }
- //} catch (NoSuchMethodError e) {
- // Log.d("PropertyValuesHolder",
- // "Can't find native method using JNI, use reflection" + e);
- //} finally {
- // mPropertyMapLock.writeLock().unlock();
- //}
- //if (mJniSetter == 0) {
- // Couldn't find method through fast JNI approach - just use reflection
- super.setupSetter(targetClass);
- //}
- }
- }
-
- static class FloatPropertyValuesHolder extends PropertyValuesHolder {
-
- // Cache JNI functions to avoid looking them up twice
- //private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap =
- // new HashMap<Class, HashMap<String, Integer>>();
- //int mJniSetter;
- //private FloatProperty mFloatProperty;
-
- FloatKeyframeSet mFloatKeyframeSet;
- float mFloatAnimatedValue;
-
- public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) {
- super(propertyName);
- mValueType = float.class;
- mKeyframeSet = keyframeSet;
- mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
- }
-
- //public FloatPropertyValuesHolder(Property property, FloatKeyframeSet keyframeSet) {
- // super(property);
- // mValueType = float.class;
- // mKeyframeSet = keyframeSet;
- // mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
- // if (property instanceof FloatProperty) {
- // mFloatProperty = (FloatProperty) mProperty;
- // }
- //}
-
- public FloatPropertyValuesHolder(String propertyName, float... values) {
- super(propertyName);
- setFloatValues(values);
- }
-
- //public FloatPropertyValuesHolder(Property property, float... values) {
- // super(property);
- // setFloatValues(values);
- // if (property instanceof FloatProperty) {
- // mFloatProperty = (FloatProperty) mProperty;
- // }
- //}
-
- @Override
- public void setFloatValues(float... values) {
- super.setFloatValues(values);
- mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet;
- }
-
- @Override
- void calculateValue(float fraction) {
- mFloatAnimatedValue = mFloatKeyframeSet.getFloatValue(fraction);
- }
-
- @Override
- Object getAnimatedValue() {
- return mFloatAnimatedValue;
- }
-
- @Override
- public FloatPropertyValuesHolder clone() {
- FloatPropertyValuesHolder newPVH = (FloatPropertyValuesHolder) super.clone();
- newPVH.mFloatKeyframeSet = (FloatKeyframeSet) newPVH.mKeyframeSet;
- return newPVH;
- }
-
- /**
- * 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 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
- */
- @Override
- void setAnimatedValue(Object target) {
- //if (mFloatProperty != null) {
- // mFloatProperty.setValue(target, mFloatAnimatedValue);
- // return;
- //}
- //if (mProperty != null) {
- // mProperty.set(target, mFloatAnimatedValue);
- // return;
- //}
- //if (mJniSetter != 0) {
- // nCallFloatMethod(target, mJniSetter, mFloatAnimatedValue);
- // return;
- //}
- if (mSetter != null) {
- try {
- mTmpValueArray[0] = mFloatAnimatedValue;
- mSetter.invoke(target, mTmpValueArray);
- } catch (InvocationTargetException e) {
- Log.e("PropertyValuesHolder", e.toString());
- } catch (IllegalAccessException e) {
- Log.e("PropertyValuesHolder", e.toString());
- }
- }
- }
-
- @Override
- void setupSetter(Class targetClass) {
- //if (mProperty != null) {
- // return;
- //}
- // Check new static hashmap<propName, int> for setter method
- //try {
- // mPropertyMapLock.writeLock().lock();
- // HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass);
- // if (propertyMap != null) {
- // Integer mJniSetterInteger = propertyMap.get(mPropertyName);
- // if (mJniSetterInteger != null) {
- // mJniSetter = mJniSetterInteger;
- // }
- // }
- // if (mJniSetter == 0) {
- // String methodName = getMethodName("set", mPropertyName);
- // mJniSetter = nGetFloatMethod(targetClass, methodName);
- // if (mJniSetter != 0) {
- // if (propertyMap == null) {
- // propertyMap = new HashMap<String, Integer>();
- // sJNISetterPropertyMap.put(targetClass, propertyMap);
- // }
- // propertyMap.put(mPropertyName, mJniSetter);
- // }
- // }
- //} catch (NoSuchMethodError e) {
- // Log.d("PropertyValuesHolder",
- // "Can't find native method using JNI, use reflection" + e);
- //} finally {
- // mPropertyMapLock.writeLock().unlock();
- //}
- //if (mJniSetter == 0) {
- // Couldn't find method through fast JNI approach - just use reflection
- super.setupSetter(targetClass);
- //}
- }
-
- }
-
- //native static private int nGetIntMethod(Class targetClass, String methodName);
- //native static private int nGetFloatMethod(Class targetClass, String methodName);
- //native static private void nCallIntMethod(Object target, int methodID, int arg);
- //native static private void nCallFloatMethod(Object target, int methodID, float arg);
-}
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java
deleted file mode 100644
index 0ea319244..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/TypeEvaluator.java
+++ /dev/null
@@ -1,44 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-/**
- * 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 ValueAnimator#setEvaluator(TypeEvaluator)
- */
-public interface TypeEvaluator<T> {
-
- /**
- * This function returns the result of linearly interpolating the start and end values, with
- * <code>fraction</code> representing the proportion between the start and end values. The
- * calculation is a simple parametric calculation: <code>result = x0 + t * (v1 - v0)</code>,
- * where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
- * and <code>t</code> is <code>fraction</code>.
- *
- * @param fraction The fraction from the starting to the ending values
- * @param startValue The start value.
- * @param endValue The end value.
- * @return A linear interpolation between the start and end values, given the
- * <code>fraction</code> parameter.
- */
- public T evaluate(float fraction, T startValue, T endValue);
-
-} \ No newline at end of file
diff --git a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java b/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java
deleted file mode 100644
index d8a12c688..000000000
--- a/actionbarsherlock/src/com/actionbarsherlock/internal/nineoldandroids/animation/ValueAnimator.java
+++ /dev/null
@@ -1,1265 +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 com.actionbarsherlock.internal.nineoldandroids.animation;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.AndroidRuntimeException;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.AnimationUtils;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
-
-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(TimeInterpolator)}.</p>
- */
-@SuppressWarnings({"rawtypes", "unchecked"})
-public class ValueAnimator extends Animator {
-
- /**
- * Internal constants
- */
-
- /*
- * The default amount of time in ms between animation frames
- */
- private static final long DEFAULT_FRAME_DELAY = 10;
-
- /**
- * 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
- */
- static final int ANIMATION_START = 0;
- static final int ANIMATION_FRAME = 1;
-
- /**
- * Values used with internal variable mPlayingState to indicate the current state of an
- * animation.
- */
- static final int STOPPED = 0; // Not yet playing
- static final int RUNNING = 1; // Playing normally
- static final int SEEKED = 2; // 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()
- long mStartTime;
-
- /**
- * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
- * to a value.
- */
- long mSeekTime = -1;
-
- // TODO: We access the following ThreadLocal variables often, some of them on every update.
- // If ThreadLocal access is significantly expensive, we may want to put all of these
- // fields into a structure sot hat we just access ThreadLocal once to get the reference
- // to that structure, then access the structure directly for each field.
-
- // The static sAnimationHandler processes the internal timing loop on which all animations
- // are based
- private static ThreadLocal<AnimationHandler> sAnimationHandler =
- new ThreadLocal<AnimationHandler>();
-
- // The per-thread list of all active animations
- private static final ThreadLocal<ArrayList<ValueAnimator>> sAnimations =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
-
- // The per-thread set of animations to be started on the next animation frame
- private static final ThreadLocal<ArrayList<ValueAnimator>> sPendingAnimations =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
-
- /**
- * Internal per-thread collections used to avoid set collisions as animations start and end
- * while being processed.
- */
- private static final ThreadLocal<ArrayList<ValueAnimator>> sDelayedAnims =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
-
- private static final ThreadLocal<ArrayList<ValueAnimator>> sEndingAnims =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
-
- private static final ThreadLocal<ArrayList<ValueAnimator>> sReadyAnims =
- new ThreadLocal<ArrayList<ValueAnimator>>() {
- @Override
- protected ArrayList<ValueAnimator> initialValue() {
- return new ArrayList<ValueAnimator>();
- }
- };
-
- // The time interpolator to be used if none is set on the animation
- private static final /*Time*/Interpolator sDefaultInterpolator =
- new AccelerateDecelerateInterpolator();
-
- // type evaluators for the primitive types handled by this implementation
- //private static final TypeEvaluator sIntEvaluator = new IntEvaluator();
- //private static final TypeEvaluator sFloatEvaluator = new FloatEvaluator();
-
- /**
- * 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 current elapsed/eased fraction, for querying in getAnimatedFraction().
- */
- private float mCurrentFraction = 0f;
-
- /**
- * 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, SEEKED.
- */
- int mPlayingState = STOPPED;
-
- /**
- * Additional playing state to indicate whether an animator has been start()'d. There is
- * some lag between a call to start() and the first animation frame. We should still note
- * that the animation has been started, even if it's first animation frame has not yet
- * happened, and reflect that state in isRunning().
- * Note that delayed animations are different: they are not started until their first
- * animation frame, which occurs after their delay elapses.
- */
- private boolean mRunning = false;
-
- /**
- * Additional playing state to indicate whether an animator has been start()'d, whether or
- * not there is a nonzero startDelay.
- */
- private boolean mStarted = false;
-
- /**
- * 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 = 300;
-
- // 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 /*Time*/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 factory methods which take parameters are more generally
- * useful.
- */
- public ValueAnimator() {
- }
-
- /**
- * Constructs and returns a ValueAnimator that animates between int values. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * @param values A set of values that the animation will animate between over time.
- * @return A ValueAnimator object that is set up to animate between the given values.
- */
- public static ValueAnimator ofInt(int... values) {
- ValueAnimator anim = new ValueAnimator();
- anim.setIntValues(values);
- return anim;
- }
-
- /**
- * Constructs and returns a ValueAnimator that animates between float values. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * @param values A set of values that the animation will animate between over time.
- * @return A ValueAnimator object that is set up to animate between the given values.
- */
- public static ValueAnimator ofFloat(float... values) {
- ValueAnimator anim = new ValueAnimator();
- anim.setFloatValues(values);
- return anim;
- }
-
- /**
- * Constructs and returns a ValueAnimator that animates between the values
- * specified in the PropertyValuesHolder objects.
- *
- * @param values A set of PropertyValuesHolder objects whose values will be animated
- * between over time.
- * @return A ValueAnimator object that is set up to animate between the given values.
- */
- public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
- ValueAnimator anim = new ValueAnimator();
- anim.setValues(values);
- return anim;
- }
- /**
- * Constructs and returns a ValueAnimator that animates between Object values. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
- * factory method also takes a TypeEvaluator object that the ValueAnimator will use
- * to perform that interpolation.
- *
- * @param evaluator A TypeEvaluator that will be called on each animation frame to
- * provide the ncessry interpolation between the Object values to derive the animated
- * value.
- * @param values A set of values that the animation will animate between over time.
- * @return A ValueAnimator object that is set up to animate between the given values.
- */
- public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
- ValueAnimator anim = new ValueAnimator();
- anim.setObjectValues(values);
- anim.setEvaluator(evaluator);
- return anim;
- }
-
- /**
- * Sets int values that will be animated between. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * <p>If there are already multiple sets of values defined for this ValueAnimator via more
- * than one PropertyValuesHolder object, this method will set the values for the first
- * of those objects.</p>
- *
- * @param values A set of values that the animation will animate between over time.
- */
- public void setIntValues(int... values) {
- if (values == null || values.length == 0) {
- return;
- }
- if (mValues == null || mValues.length == 0) {
- setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofInt("", values)});
- } else {
- PropertyValuesHolder valuesHolder = mValues[0];
- valuesHolder.setIntValues(values);
- }
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
-
- /**
- * Sets float values that will be animated between. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * <p>If there are already multiple sets of values defined for this ValueAnimator via more
- * than one PropertyValuesHolder object, this method will set the values for the first
- * of those objects.</p>
- *
- * @param values A set of values that the animation will animate between over time.
- */
- public void setFloatValues(float... values) {
- if (values == null || values.length == 0) {
- return;
- }
- if (mValues == null || mValues.length == 0) {
- setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofFloat("", values)});
- } else {
- PropertyValuesHolder valuesHolder = mValues[0];
- valuesHolder.setFloatValues(values);
- }
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
-
- /**
- * Sets the values to animate between for this animation. A single
- * value implies that that value is the one being animated to. However, this is not typically
- * useful in a ValueAnimator object because there is no way for the object to determine the
- * starting value for the animation (unlike ObjectAnimator, which can derive that value
- * from the target object and property being animated). Therefore, there should typically
- * be two or more values.
- *
- * <p>If there are already multiple sets of values defined for this ValueAnimator via more
- * than one PropertyValuesHolder object, this method will set the values for the first
- * of those objects.</p>
- *
- * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
- * between these value objects. ValueAnimator only knows how to interpolate between the
- * primitive types specified in the other setValues() methods.</p>
- *
- * @param values The set of values to animate between.
- */
- public void setObjectValues(Object... values) {
- if (values == null || values.length == 0) {
- return;
- }
- if (mValues == null || mValues.length == 0) {
- setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofObject("",
- (TypeEvaluator)null, values)});
- } else {
- PropertyValuesHolder valuesHolder = mValues[0];
- valuesHolder.setObjectValues(values);
- }
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
-
- /**
- * 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 = values[i];
- mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
- }
- // New property/values/target should cause re-initialization prior to starting
- mInitialized = false;
- }
-
- /**
- * 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;
- }
-
- /**
- * 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();
- }
- mInitialized = true;
- }
- }
-
-
- /**
- * Sets the length of the animation. The default duration is 300 milliseconds.
- *
- * @param duration The length of the animation, in milliseconds. This value cannot
- * be negative.
- * @return ValueAnimator The object called with setDuration(). This return
- * value makes it easier to compose statements together that construct and then set the
- * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
- */
- public ValueAnimator setDuration(long duration) {
- if (duration < 0) {
- throw new IllegalArgumentException("Animators cannot have negative duration: " +
- duration);
- }
- mDuration = duration;
- return this;
- }
-
- /**
- * Gets the length of the animation. The default duration is 300 milliseconds.
- *
- * @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;
- ArrayList<ValueAnimator> animations = sAnimations.get();
- ArrayList<ValueAnimator> delayedAnims = sDelayedAnims.get();
- switch (msg.what) {
- // TODO: should we avoid sending frame message when starting if we
- // were already running?
- case ANIMATION_START:
- ArrayList<ValueAnimator> pendingAnimations = sPendingAnimations.get();
- if (animations.size() > 0 || delayedAnims.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 (pendingAnimations.size() > 0) {
- ArrayList<ValueAnimator> pendingCopy =
- (ArrayList<ValueAnimator>) pendingAnimations.clone();
- pendingAnimations.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.startAnimation();
- } else {
- delayedAnims.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();
- ArrayList<ValueAnimator> readyAnims = sReadyAnims.get();
- ArrayList<ValueAnimator> endingAnims = sEndingAnims.get();
-
- // First, process animations currently sitting on the delayed queue, adding
- // them to the active animations if they are ready
- int numDelayedAnims = delayedAnims.size();
- for (int i = 0; i < numDelayedAnims; ++i) {
- ValueAnimator anim = delayedAnims.get(i);
- if (anim.delayedAnimationFrame(currentTime)) {
- readyAnims.add(anim);
- }
- }
- int numReadyAnims = readyAnims.size();
- if (numReadyAnims > 0) {
- for (int i = 0; i < numReadyAnims; ++i) {
- ValueAnimator anim = readyAnims.get(i);
- anim.startAnimation();
- anim.mRunning = true;
- delayedAnims.remove(anim);
- }
- readyAnims.clear();
- }
-
- // Now process all active animations. The return value from animationFrame()
- // tells the handler whether it should now be ended
- int numAnims = animations.size();
- int i = 0;
- while (i < numAnims) {
- ValueAnimator anim = animations.get(i);
- if (anim.animationFrame(currentTime)) {
- endingAnims.add(anim);
- }
- if (animations.size() == numAnims) {
- ++i;
- } else {
- // An animation might be canceled or ended by client code
- // during the animation frame. Check to see if this happened by
- // seeing whether the current index is the same as it was before
- // calling animationFrame(). Another approach would be to copy
- // animations to a temporary list and process that list instead,
- // but that entails garbage and processing overhead that would
- // be nice to avoid.
- --numAnims;
- endingAnims.remove(anim);
- }
- }
- if (endingAnims.size() > 0) {
- for (i = 0; i < endingAnims.size(); ++i) {
- endingAnims.get(i).endAnimation();
- }
- endingAnims.clear();
- }
-
- // If there are still active or delayed animations, call the handler again
- // after the frameDelay
- if (callAgain && (!animations.isEmpty() || !delayedAnims.isEmpty())) {
- sendEmptyMessageDelayed(ANIMATION_FRAME, Math.max(0, sFrameDelay -
- (AnimationUtils.currentAnimationTimeMillis() - currentTime)));
- }
- 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 all listeners from the set listening to frame updates for this animation.
- */
- public void removeAllUpdateListeners() {
- if (mUpdateListeners == null) {
- return;
- }
- mUpdateListeners.clear();
- mUpdateListeners = null;
- }
-
- /**
- * 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. A value of <code>null</code>
- * will result in linear interpolation.
- */
- @Override
- public void setInterpolator(/*Time*/Interpolator value) {
- if (value != null) {
- mInterpolator = value;
- } else {
- mInterpolator = new LinearInterpolator();
- }
- }
-
- /**
- * Returns the timing interpolator that this ValueAnimator uses.
- *
- * @return The timing interpolator for this ValueAnimator.
- */
- public /*Time*/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 or int 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 ArgbEvaluator}
- * 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.
- *
- * <p>The animation started by calling this method will be run on the thread that called
- * this method. This thread should have a Looper on it (a runtime exception will be thrown if
- * this is not the case). Also, if the animation will animate
- * properties of objects in the view hierarchy, then the calling thread should be the UI
- * thread for that view hierarchy.</p>
- *
- * @param playBackwards Whether the ValueAnimator should start playing in reverse.
- */
- private void start(boolean playBackwards) {
- if (Looper.myLooper() == null) {
- throw new AndroidRuntimeException("Animators may only be run on Looper threads");
- }
- mPlayingBackwards = playBackwards;
- mCurrentIteration = 0;
- mPlayingState = STOPPED;
- mStarted = true;
- mStartedDelay = false;
- sPendingAnimations.get().add(this);
- if (mStartDelay == 0) {
- // This sets the initial value of the animation, prior to actually starting it running
- setCurrentPlayTime(getCurrentPlayTime());
- mPlayingState = STOPPED;
- mRunning = true;
-
- if (mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationStart(this);
- }
- }
- }
- AnimationHandler animationHandler = sAnimationHandler.get();
- if (animationHandler == null) {
- animationHandler = new AnimationHandler();
- sAnimationHandler.set(animationHandler);
- }
- animationHandler.sendEmptyMessage(ANIMATION_START);
- }
-
- @Override
- public void start() {
- start(false);
- }
-
- @Override
- public void cancel() {
- // Only cancel if the animation is actually running or has been started and is about
- // to run
- if (mPlayingState != STOPPED || sPendingAnimations.get().contains(this) ||
- sDelayedAnims.get().contains(this)) {
- // Only notify listeners if the animator has actually started
- if (mRunning && mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- for (AnimatorListener listener : tmpListeners) {
- listener.onAnimationCancel(this);
- }
- }
- endAnimation();
- }
- }
-
- @Override
- public void end() {
- if (!sAnimations.get().contains(this) && !sPendingAnimations.get().contains(this)) {
- // Special case if the animation has not yet started; get it ready for ending
- mStartedDelay = false;
- startAnimation();
- } else if (!mInitialized) {
- initAnimation();
- }
- // 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);
- }
- endAnimation();
- }
-
- @Override
- public boolean isRunning() {
- return (mPlayingState == RUNNING || mRunning);
- }
-
- @Override
- public boolean isStarted() {
- return mStarted;
- }
-
- /**
- * 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.get().remove(this);
- sPendingAnimations.get().remove(this);
- sDelayedAnims.get().remove(this);
- mPlayingState = STOPPED;
- if (mRunning && mListeners != null) {
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onAnimationEnd(this);
- }
- }
- mRunning = false;
- mStarted = false;
- }
-
- /**
- * 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.get().add(this);
- if (mStartDelay > 0 && mListeners != null) {
- // Listeners were already notified in start() if startDelay is 0; this is
- // just for delayed animations
- ArrayList<AnimatorListener> tmpListeners =
- (ArrayList<AnimatorListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).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 (!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.
- */
- 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 = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
- if (fraction >= 1f) {
- if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
- // Time to repeat
- if (mListeners != null) {
- int numListeners = mListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- mListeners.get(i).onAnimationRepeat(this);
- }
- }
- if (mRepeatMode == REVERSE) {
- mPlayingBackwards = mPlayingBackwards ? false : true;
- }
- mCurrentIteration += (int)fraction;
- fraction = fraction % 1f;
- mStartTime += mDuration;
- } else {
- done = true;
- fraction = Math.min(fraction, 1.0f);
- }
- }
- if (mPlayingBackwards) {
- fraction = 1f - fraction;
- }
- animateValue(fraction);
- break;
- }
-
- return done;
- }
-
- /**
- * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
- * the most recent frame update on the animation.
- *
- * @return Elapsed/interpolated fraction of the animation.
- */
- public float getAnimatedFraction() {
- return mCurrentFraction;
- }
-
- /**
- * 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);
- mCurrentFraction = 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];
- anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
- for (int i = 0; i < numValues; ++i) {
- PropertyValuesHolder newValuesHolder = oldValues[i].clone();
- anim.mValues[i] = newValuesHolder;
- anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
- }
- }
- 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);
-
- }
-
- /**
- * Return the number of animations currently running.
- *
- * Used by StrictMode internally to annotate violations. Only
- * called on the main thread.
- *
- * @hide
- */
- public static int getCurrentAnimationsCount() {
- return sAnimations.get().size();
- }
-
- /**
- * Clear all animations on this thread, without canceling or ending them.
- * This should be used with caution.
- *
- * @hide
- */
- public static void clearAllAnimations() {
- sAnimations.get().clear();
- sPendingAnimations.get().clear();
- sDelayedAnims.get().clear();
- }
-
- @Override
- public String toString() {
- String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
- if (mValues != null) {
- for (int i = 0; i < mValues.length; ++i) {
- returnVal += "\n " + mValues[i].toString();
- }
- }
- return returnVal;
- }
-}