Merge "Change animator xml importing to use new inflater class"

This commit is contained in:
Chet Haase
2010-08-25 08:17:26 -07:00
committed by Android (Google) Code Review
6 changed files with 351 additions and 246 deletions

View File

@@ -19966,6 +19966,40 @@
</parameter>
</method>
</interface>
<class name="AnimatableInflater"
extends="java.lang.Object"
abstract="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<constructor name="AnimatableInflater"
type="android.animation.AnimatableInflater"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
</constructor>
<method name="loadAnimatable"
return="android.animation.Animatable"
abstract="false"
native="false"
synchronized="false"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
<parameter name="id" type="int">
</parameter>
<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
</exception>
</method>
</class>
<class name="AnimatableListenerAdapter"
extends="java.lang.Object"
abstract="true"
@@ -20052,10 +20086,6 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
</constructor>
<constructor name="Animator"
type="android.animation.Animator"
@@ -20231,6 +20261,19 @@
<parameter name="playTime" type="long">
</parameter>
</method>
<method name="setDuration"
return="void"
abstract="false"
native="false"
synchronized="false"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="duration" type="long">
</parameter>
</method>
<method name="setEvaluator"
return="void"
abstract="false"
@@ -20653,10 +20696,6 @@
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
<parameter name="attrs" type="android.util.AttributeSet">
</parameter>
</constructor>
<constructor name="PropertyAnimator"
type="android.animation.PropertyAnimator"
@@ -205789,23 +205828,6 @@
<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
</exception>
</method>
<method name="loadAnimator"
return="android.animation.Animatable"
abstract="false"
native="false"
synchronized="false"
static="true"
final="false"
deprecated="not deprecated"
visibility="public"
>
<parameter name="context" type="android.content.Context">
</parameter>
<parameter name="id" type="int">
</parameter>
<exception name="Resources.NotFoundException" type="android.content.res.Resources.NotFoundException">
</exception>
</method>
<method name="loadInterpolator"
return="android.view.animation.Interpolator"
abstract="false"

View File

@@ -0,0 +1,269 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.animation;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.content.res.Resources.NotFoundException;
import android.util.AttributeSet;
import android.util.Xml;
import android.view.animation.AnimationUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
/**
* This class is used to instantiate menu XML files into Animatable objects.
* <p>
* For performance reasons, menu inflation relies heavily on pre-processing of
* XML files that is done at build time. Therefore, it is not currently possible
* 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.
* <em>something</em> 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<Animatable> 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<Animatable>();
}
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;
}
}

View File

@@ -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<T> 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<T> extends Animatable {
*/
HashMap<String, PropertyValuesHolder> mValuesMap;
/**
* The type of the values, as determined by the valueFrom/valueTo properties.
*/
Class mValueType;
/**
* Public constants
*/
@@ -234,76 +218,13 @@ public class Animator<T> 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<String, PropertyValuesHolder>(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<T> 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<T> 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<T> 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);

View File

@@ -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<T> extends Animator<T> {
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<T> extends Animator<T> {
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.

View File

@@ -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) {

View File

@@ -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<Animatable> 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<Animatable>();
}
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 {