diff --git a/api/current.xml b/api/current.xml
index cbbf3d1fe8bfc..8ff263c94f615 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -19966,6 +19966,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+ * For performance reasons, menu inflation relies heavily on pre-processing of
+ * XML files that is done at build time. Therefore, it is not currently possible
+ * to use MenuInflater with an XmlPullParser over a plain XML file at runtime;
+ * it only works with an XmlPullParser returned from a compiled resource (R.
+ * something file.)
+ */
+public class AnimatableInflater {
+
+ /**
+ * These flags are used when parsing Sequencer objects
+ */
+ private static final int TOGETHER = 0;
+ private static final int SEQUENTIALLY = 1;
+
+ /**
+ * Enum values used in XML attributes to indicate the value for mValueType
+ */
+ private static final int VALUE_TYPE_FLOAT = 0;
+ private static final int VALUE_TYPE_INT = 1;
+ private static final int VALUE_TYPE_DOUBLE = 2;
+ private static final int VALUE_TYPE_COLOR = 3;
+ private static final int VALUE_TYPE_CUSTOM = 4;
+
+ /**
+ * Loads an {@link Animatable} object from a resource
+ *
+ * @param context Application context used to access resources
+ * @param id The resource id of the animation to load
+ * @return The animatable object reference by the specified id
+ * @throws android.content.res.Resources.NotFoundException when the animation cannot be loaded
+ */
+ public static Animatable loadAnimatable(Context context, int id)
+ throws NotFoundException {
+
+ XmlResourceParser parser = null;
+ try {
+ parser = context.getResources().getAnimation(id);
+ return createAnimatableFromXml(context, parser);
+ } catch (XmlPullParserException ex) {
+ Resources.NotFoundException rnf =
+ new Resources.NotFoundException("Can't load animation resource ID #0x" +
+ Integer.toHexString(id));
+ rnf.initCause(ex);
+ throw rnf;
+ } catch (IOException ex) {
+ Resources.NotFoundException rnf =
+ new Resources.NotFoundException("Can't load animation resource ID #0x" +
+ Integer.toHexString(id));
+ rnf.initCause(ex);
+ throw rnf;
+ } finally {
+ if (parser != null) parser.close();
+ }
+ }
+
+ private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser)
+ throws XmlPullParserException, IOException {
+
+ return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
+ }
+
+ private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser,
+ AttributeSet attrs, Sequencer parent, int sequenceOrdering)
+ throws XmlPullParserException, IOException {
+
+ Animatable anim = null;
+ ArrayList childAnims = null;
+
+ // Make sure we are on a start tag.
+ int type;
+ int depth = parser.getDepth();
+
+ while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
+ && type != XmlPullParser.END_DOCUMENT) {
+
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ String name = parser.getName();
+
+ if (name.equals("property")) {
+ anim = loadPropertyAnimator(c, attrs);
+ } else if (name.equals("animator")) {
+ anim = loadAnimator(c, attrs, null);
+ } else if (name.equals("sequencer")) {
+ anim = new Sequencer();
+ TypedArray a = c.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Sequencer);
+ int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering,
+ TOGETHER);
+ createAnimatableFromXml(c, parser, attrs, (Sequencer) anim, ordering);
+ a.recycle();
+ } else {
+ throw new RuntimeException("Unknown animator name: " + parser.getName());
+ }
+
+ if (parent != null) {
+ if (childAnims == null) {
+ childAnims = new ArrayList();
+ }
+ childAnims.add(anim);
+ }
+ }
+ if (parent != null && childAnims != null) {
+ Animatable[] animsArray = new Animatable[childAnims.size()];
+ int index = 0;
+ for (Animatable a : childAnims) {
+ animsArray[index++] = a;
+ }
+ if (sequenceOrdering == TOGETHER) {
+ parent.playTogether(animsArray);
+ } else {
+ parent.playSequentially(animsArray);
+ }
+ }
+
+ return anim;
+
+ }
+
+ private static PropertyAnimator loadPropertyAnimator(Context context, AttributeSet attrs)
+ throws NotFoundException {
+
+ PropertyAnimator anim = new PropertyAnimator();
+
+ loadAnimator(context, attrs, anim);
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.PropertyAnimator);
+
+ String propertyName = a.getString(com.android.internal.R.styleable.PropertyAnimator_propertyName);
+
+ anim.setPropertyName(propertyName);
+
+ a.recycle();
+
+ return anim;
+ }
+
+ /**
+ * Creates a new animation whose parameters come from the specified context and
+ * attributes set.
+ *
+ * @param context the application environment
+ * @param attrs the set of attributes holding the animation parameters
+ */
+ private static Animator loadAnimator(Context context, AttributeSet attrs, Animator anim)
+ throws NotFoundException {
+
+ TypedArray a =
+ context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator);
+
+ long duration = a.getInt(com.android.internal.R.styleable.Animator_duration, 0);
+
+ long startDelay = a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
+
+ int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
+ VALUE_TYPE_FLOAT);
+
+ Object valueFrom = null;
+ Object valueTo = null;
+ TypeEvaluator evaluator = null;
+
+ switch (valueType) {
+ case VALUE_TYPE_FLOAT:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
+ }
+ break;
+ case VALUE_TYPE_COLOR:
+ evaluator = new RGBEvaluator();
+ // fall through to pick up values
+ case VALUE_TYPE_INT:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getInteger(com.android.internal.R.styleable.Animator_valueFrom, 0);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0);
+ }
+ break;
+ case VALUE_TYPE_DOUBLE:
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = (Double)((Float)(a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f))).doubleValue();
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = (Double)((Float)a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f)).doubleValue();
+ }
+ break;
+ case VALUE_TYPE_CUSTOM:
+ // TODO: How to get an 'Object' value?
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueFrom)) {
+ valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_valueTo)) {
+ valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
+ }
+ break;
+ }
+
+ if (anim == null) {
+ anim = new Animator(duration, valueFrom, valueTo);
+ } else {
+ anim.setDuration(duration);
+ anim.setValues(valueFrom, valueTo);
+ }
+
+ anim.setStartDelay(startDelay);
+
+ if (a.hasValue(com.android.internal.R.styleable.Animator_repeatCount)) {
+ anim.setRepeatCount(
+ a.getInt(com.android.internal.R.styleable.Animator_repeatCount, 0));
+ }
+ if (a.hasValue(com.android.internal.R.styleable.Animator_repeatMode)) {
+ anim.setRepeatMode(
+ a.getInt(com.android.internal.R.styleable.Animator_repeatMode,
+ Animator.RESTART));
+ }
+ if (evaluator != null) {
+ anim.setEvaluator(evaluator);
+ }
+
+ final int resID =
+ a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
+ if (resID > 0) {
+ anim.setInterpolator(AnimationUtils.loadInterpolator(context, resID));
+ }
+ a.recycle();
+
+ return anim;
+ }
+}
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index eca5f0d29601a..18017bae0dc32 100755
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -17,11 +17,9 @@
package android.animation;
import android.content.Context;
-import android.content.res.TypedArray;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -69,15 +67,6 @@ public class Animator extends Animatable {
private static final int ENDED = 3; // end() called - need to end it
private static final int SEEKED = 4; // Seeked to some time value
- /**
- * Enum values used in XML attributes to indicate the value for mValueType
- */
- private static final int VALUE_TYPE_FLOAT = 0;
- private static final int VALUE_TYPE_INT = 1;
- private static final int VALUE_TYPE_DOUBLE = 2;
- private static final int VALUE_TYPE_COLOR = 3;
- private static final int VALUE_TYPE_CUSTOM = 4;
-
/**
* Internal variables
* NOTE: This object implements the clone() method, making a deep copy of any referenced
@@ -208,11 +197,6 @@ public class Animator extends Animatable {
*/
HashMap mValuesMap;
- /**
- * The type of the values, as determined by the valueFrom/valueTo properties.
- */
- Class mValueType;
-
/**
* Public constants
*/
@@ -234,76 +218,13 @@ public class Animator extends Animatable {
public static final int INFINITE = -1;
/**
- * Creates a new animation whose parameters come from the specified context and
- * attributes set.
- *
- * @param context the application environment
- * @param attrs the set of attributes holding the animation parameters
+ * Creates a new Animator object. This default constructor is primarily for
+ * use internally; the other constructors which take parameters are more generally
+ * useful.
*/
- public Animator(Context context, AttributeSet attrs) {
- TypedArray a =
- context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Animator);
-
- mDuration = (long) a.getInt(com.android.internal.R.styleable.Animator_duration, 0);
-
- mStartDelay = (long) a.getInt(com.android.internal.R.styleable.Animator_startOffset, 0);
-
- final int resID =
- a.getResourceId(com.android.internal.R.styleable.Animator_interpolator, 0);
- if (resID > 0) {
- setInterpolator(AnimationUtils.loadInterpolator(context, resID));
- }
- int valueType = a.getInt(com.android.internal.R.styleable.Animator_valueType,
- VALUE_TYPE_FLOAT);
-
- Object valueFrom = null;
- Object valueTo = null;
-
- switch (valueType) {
- case VALUE_TYPE_FLOAT:
- valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = float.class;
- break;
- case VALUE_TYPE_INT:
- valueFrom = a.getInt(com.android.internal.R.styleable.Animator_valueFrom, 0);
- valueTo = a.getInt(com.android.internal.R.styleable.Animator_valueTo, 0);
- mValueType = int.class;
- break;
- case VALUE_TYPE_DOUBLE:
- valueFrom = (double)
- a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = (double)
- a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = double.class;
- break;
- case VALUE_TYPE_COLOR:
- valueFrom = a.getInt(com.android.internal.R.styleable.Animator_valueFrom, 0);
- valueTo = a.getInt(com.android.internal.R.styleable.Animator_valueTo, 0);
- setEvaluator(new RGBEvaluator());
- mValueType = int.class;
- break;
- case VALUE_TYPE_CUSTOM:
- // TODO: How to get an 'Object' value?
- valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f);
- valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f);
- mValueType = Object.class;
- break;
- }
-
- PropertyValuesHolder valuesHolder = new PropertyValuesHolder("", valueFrom, valueTo);
- mValues = new PropertyValuesHolder[1];
- mValues[0] = valuesHolder;
- mValuesMap = new HashMap(1);
- mValuesMap.put("", valuesHolder);
-
- mRepeatCount = a.getInt(com.android.internal.R.styleable.Animator_repeatCount, mRepeatCount);
- mRepeatMode = a.getInt(com.android.internal.R.styleable.Animator_repeatMode, RESTART);
-
- a.recycle();
+ public Animator() {
}
-
/**
* Constructs an Animator object with the specified duration and set of
* values. If the values are a set of PropertyValuesHolder objects, then these objects
@@ -373,6 +294,25 @@ public class Animator extends Animatable {
mInitialized = true;
}
+
+ /**
+ * Sets the length of the animation.
+ *
+ * @param duration The length of the animation, in milliseconds.
+ */
+ public void setDuration(long duration) {
+ mDuration = duration;
+ }
+
+ /**
+ * Gets the length of the animation.
+ *
+ * @return The length of the animation, in milliseconds.
+ */
+ public long getDuration() {
+ return mDuration;
+ }
+
/**
* Sets the position of the animation to the specified point in time. This time should
* be between 0 and the total duration of the animation, including any repetition. If
@@ -723,11 +663,11 @@ public class Animator extends Animatable {
* @param playBackwards Whether the Animator should start playing in reverse.
*/
private void start(boolean playBackwards) {
+ mPlayingBackwards = playBackwards;
if ((mStartDelay == 0) && (Thread.currentThread() == Looper.getMainLooper().getThread())) {
// This sets the initial value of the animation, prior to actually starting it running
setCurrentPlayTime(getCurrentPlayTime());
}
- mPlayingBackwards = playBackwards;
mPlayingState = STOPPED;
sPendingAnimations.add(this);
if (sAnimationHandler == null) {
@@ -738,15 +678,6 @@ public class Animator extends Animatable {
sAnimationHandler.sendEmptyMessage(ANIMATION_START);
}
- /**
- * Returns the duration that this animation will run for.
- *
- * @return The length in time of the animation, in milliseconds.
- */
- public long getDuration() {
- return mDuration;
- }
-
@Override
public void start() {
start(false);
diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/PropertyAnimator.java
index 022ca7ddc999c..8a6edcc72f3e0 100644
--- a/core/java/android/animation/PropertyAnimator.java
+++ b/core/java/android/animation/PropertyAnimator.java
@@ -16,9 +16,6 @@
package android.animation;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.util.AttributeSet;
import android.util.Log;
import java.lang.reflect.Method;
@@ -80,25 +77,6 @@ public final class PropertyAnimator extends Animator {
return mPropertyName;
}
- /**
- * Creates a new animation whose parameters come from the specified context and
- * attributes set.
- *
- * @param context the application environment
- * @param attrs the set of attributes holding the animation parameters
- */
- public PropertyAnimator(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- TypedArray a = context.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.PropertyAnimator);
-
- setPropertyName(a.getString(
- com.android.internal.R.styleable.PropertyAnimator_propertyName));
-
-
- a.recycle();
- }
/**
* 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
@@ -129,6 +107,14 @@ public final class PropertyAnimator extends Animator {
return returnVal;
}
+ /**
+ * Creates a new PropertyAnimator object. This default constructor is primarily for
+ * use internally; the other constructors which take parameters are more generally
+ * useful.
+ */
+ public PropertyAnimator() {
+ }
+
/**
* A constructor that takes a single property name and set of values. This constructor is
* used in the simple case of animating a single property.
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index f190d0d3dd9b7..c63233e4b6493 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -17,6 +17,7 @@
package android.app;
import android.animation.Animatable;
+import android.animation.AnimatableInflater;
import android.animation.PropertyAnimator;
import android.animation.Sequencer;
import android.content.res.TypedArray;
@@ -31,7 +32,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.view.animation.AnimationUtils;
import java.util.ArrayList;
@@ -257,7 +257,7 @@ final class FragmentManagerImpl implements FragmentManager {
}
if (fragment.mNextAnim != 0) {
- Animatable anim = AnimationUtils.loadAnimator(mActivity, fragment.mNextAnim);
+ Animatable anim = AnimatableInflater.loadAnimatable(mActivity, fragment.mNextAnim);
if (anim != null) {
return anim;
}
@@ -288,7 +288,7 @@ final class FragmentManagerImpl implements FragmentManager {
return null;
}
- return AnimationUtils.loadAnimator(mActivity, anim);
+ return AnimatableInflater.loadAnimatable(mActivity, anim);
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle) {
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index 8e4cf67d1fea5..c090f8e5f083a 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -16,12 +16,6 @@
package android.view.animation;
-import android.animation.Animatable;
-import android.animation.Animator;
-import android.animation.PropertyAnimator;
-import android.animation.Sequencer;
-import android.content.res.TypedArray;
-import android.util.TypedValue;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -33,7 +27,6 @@ import android.util.Xml;
import android.os.SystemClock;
import java.io.IOException;
-import java.util.ArrayList;
/**
* Defines common utilities for working with animations.
@@ -92,42 +85,6 @@ public class AnimationUtils {
}
}
- /**
- * Loads an {@link Animation} object from a resource
- *
- * @param context Application context used to access resources
- * @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
- * @throws NotFoundException when the animation cannot be loaded
- */
- public static Animatable loadAnimator(Context context, int id)
- throws NotFoundException {
-
- XmlResourceParser parser = null;
- try {
- parser = context.getResources().getAnimation(id);
- return createAnimatableFromXml(context, parser);
- } catch (XmlPullParserException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } catch (IOException ex) {
- NotFoundException rnf = new NotFoundException("Can't load animation resource ID #0x" +
- Integer.toHexString(id));
- rnf.initCause(ex);
- throw rnf;
- } finally {
- if (parser != null) parser.close();
- }
- }
-
- private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser)
- throws XmlPullParserException, IOException {
-
- return createAnimatableFromXml(c, parser, Xml.asAttributeSet(parser), null, 0);
- }
-
private static Animation createAnimationFromXml(Context c, XmlPullParser parser)
throws XmlPullParserException, IOException {
@@ -176,66 +133,6 @@ public class AnimationUtils {
}
- private static Animatable createAnimatableFromXml(Context c, XmlPullParser parser,
- AttributeSet attrs, Sequencer parent, int sequenceOrdering)
- throws XmlPullParserException, IOException {
-
- Animatable anim = null;
- ArrayList childAnims = null;
-
- // Make sure we are on a start tag.
- int type;
- int depth = parser.getDepth();
-
- while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
- && type != XmlPullParser.END_DOCUMENT) {
-
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
-
- String name = parser.getName();
-
- if (name.equals("property")) {
- anim = new PropertyAnimator(c, attrs);
- } else if (name.equals("animator")) {
- anim = new Animator(c, attrs);
- } else if (name.equals("sequencer")) {
- anim = new Sequencer();
- TypedArray a = c.obtainStyledAttributes(attrs,
- com.android.internal.R.styleable.Sequencer);
- int ordering = a.getInt(com.android.internal.R.styleable.Sequencer_ordering,
- TOGETHER);
- createAnimatableFromXml(c, parser, attrs, (Sequencer) anim, ordering);
- a.recycle();
- } else {
- throw new RuntimeException("Unknown animator name: " + parser.getName());
- }
-
- if (parent != null) {
- if (childAnims == null) {
- childAnims = new ArrayList();
- }
- childAnims.add(anim);
- }
- }
- if (parent != null && childAnims != null) {
- Animatable[] animsArray = new Animatable[childAnims.size()];
- int index = 0;
- for (Animatable a : childAnims) {
- animsArray[index++] = a;
- }
- if (sequenceOrdering == TOGETHER) {
- parent.playTogether(animsArray);
- } else {
- parent.playSequentially(animsArray);
- }
- }
-
- return anim;
-
- }
-
public static LayoutAnimationController loadLayoutAnimation(Context context, int id)
throws NotFoundException {