From 602e4d3824bf8b9cb9f817375d195b969712176a Mon Sep 17 00:00:00 2001 From: Chet Haase Date: Mon, 16 Aug 2010 08:57:23 -0700 Subject: [PATCH] Adding animation facilities to simplify layout transitions Change-Id: I70992a0dff6a75727f51abcfdfc7d7f2c2a8c101 --- api/current.xml | 22 ++++ core/java/android/animation/Animator.java | 109 ++++++++++-------- .../android/animation/PropertyAnimator.java | 21 ++-- .../animation/PropertyValuesHolder.java | 9 +- 4 files changed, 100 insertions(+), 61 deletions(-) diff --git a/api/current.xml b/api/current.xml index d935c387b1cc3..54ba4a333f81e 100644 --- a/api/current.xml +++ b/api/current.xml @@ -20080,6 +20080,17 @@ visibility="public" > + + + + extends Animatable { /** * The property/value sets being animated. */ - HashMap mValues; + PropertyValuesHolder[] mValues; /** - * This value is used in the simple/common case of animating just one value; the user - * may call getAnimatedValue(), which should return the value of the first (and only) - * ProeprtyValuesHolder animated value, which is looked up using this string. + * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values + * by property name during calls to getAnimatedValue(String). */ - String mFirstPropertyName; - + HashMap mValuesMap; /** * The type of the values, as determined by the valueFrom/valueTo properties. @@ -290,11 +289,11 @@ public class Animator extends Animatable { break; } - mValues = new HashMap(1); - mFirstPropertyName = ""; - PropertyValuesHolder valuesHolder = new PropertyValuesHolder(mFirstPropertyName, - valueFrom, valueTo); - mValues.put(mFirstPropertyName, valuesHolder); + 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); @@ -323,15 +322,11 @@ public class Animator extends Animatable { public void setValues(PropertyValuesHolder... values) { int numValues = values.length; - mValues = new HashMap(numValues); + mValues = values; + mValuesMap = new HashMap(numValues); for (int i = 0; i < numValues; ++i) { PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i]; - mValues.put(valuesHolder.getPropertyName(), valuesHolder); - } - if (numValues > 0 && values[0] != null) { - mFirstPropertyName = ((PropertyValuesHolder) values[0]).getPropertyName(); - } else { - mFirstPropertyName = ""; + mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder); } } @@ -348,26 +343,12 @@ public class Animator extends Animatable { * @param values The set of values to animate between. */ public void setValues(T... values) { - if (values[0] instanceof PropertyValuesHolder) { - int numValues = values.length; - mValues = new HashMap(numValues); - for (int i = 0; i < numValues; ++i) { - PropertyValuesHolder valuesHolder = (PropertyValuesHolder) values[i]; - mValues.put(valuesHolder.getPropertyName(), valuesHolder); - } - if (numValues > 0 && values[0] != null) { - mFirstPropertyName = ((PropertyValuesHolder) values[0]).getPropertyName(); - } else { - mFirstPropertyName = ""; - } + if (mValues == null || mValues.length == 0) { + setValues(new PropertyValuesHolder[]{ + new PropertyValuesHolder("", (Object[])values)}); } else { - if (mValues == null) { - setValues(new PropertyValuesHolder[]{ - new PropertyValuesHolder("", (Object[])values)}); - } else { - PropertyValuesHolder valuesHolder = mValues.get(mFirstPropertyName); - valuesHolder.setValues(values); - } + PropertyValuesHolder valuesHolder = mValues[0]; + valuesHolder.setValues(values); } } @@ -382,8 +363,9 @@ public class Animator extends Animatable { * that internal mechanisms for the animation are set up correctly.

*/ void initAnimation() { - for (PropertyValuesHolder pvHolder: mValues.values()) { - pvHolder.init(); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].init(); } mCurrentIteration = 0; mInitialized = true; @@ -394,8 +376,8 @@ public class Animator extends Animatable { * 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 seek() will - * set the current playing time to this value and continue playing from that point. + * 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. */ @@ -587,7 +569,11 @@ public class Animator extends Animatable { * returns the animated value for the first of those objects. */ public Object getAnimatedValue() { - return getAnimatedValue(mFirstPropertyName); + if (mValues != null && mValues.length > 0) { + return mValues[0].getAnimatedValue(); + } + // Shouldn't get here; should always have values unless Animator was set up wrong + return null; } /** @@ -601,7 +587,13 @@ public class Animator extends Animatable { * by this Animator. */ public Object getAnimatedValue(String propertyName) { - return mValues.get(mFirstPropertyName).getAnimatedValue(); + PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName); + if (valuesHolder != null) { + return valuesHolder.getAnimatedValue(); + } else { + // At least avoid crashing if called with bogus propertyName + return null; + } } /** @@ -690,6 +682,15 @@ public class Animator extends Animatable { } } + /** + * Returns the timing interpolator that this Animator uses. + * + * @return The timing interpolator for this Animator. + */ + public Interpolator getInterpolator() { + return mInterpolator; + } + /** * The type evaluator to be used when calculating the animated values of this animation. * The system will automatically assign a float, int, or double evaluator based on the type @@ -707,8 +708,8 @@ public class Animator extends Animatable { * @param value the evaluator to be used this animation */ public void setEvaluator(TypeEvaluator value) { - if (value != null && mValues != null) { - mValues.get(mFirstPropertyName).setEvaluator(value); + if (value != null && mValues != null && mValues.length > 0) { + mValues[0].setEvaluator(value); } } @@ -720,6 +721,10 @@ public class Animator extends Animatable { * @param playBackwards Whether the Animator should start playing in reverse. */ private void start(boolean 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); @@ -731,6 +736,15 @@ 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); @@ -928,8 +942,9 @@ public class Animator extends Animatable { */ void animateValue(float fraction) { fraction = mInterpolator.getInterpolation(fraction); - for (PropertyValuesHolder valuesHolder : mValues.values()) { - valuesHolder.calculateValue(fraction); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].calculateValue(fraction); } if (mUpdateListeners != null) { int numListeners = mUpdateListeners.size(); diff --git a/core/java/android/animation/PropertyAnimator.java b/core/java/android/animation/PropertyAnimator.java index 9366a713971e1..1a010a982920c 100644 --- a/core/java/android/animation/PropertyAnimator.java +++ b/core/java/android/animation/PropertyAnimator.java @@ -21,10 +21,7 @@ import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.Log; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.concurrent.locks.ReentrantReadWriteLock; /** * This subclass of {@link Animator} provides support for animating properties on target objects. @@ -61,10 +58,12 @@ public final class PropertyAnimator extends Animator { */ public void setPropertyName(String propertyName) { if (mValues != null) { - // should always be the case - PropertyValuesHolder valuesHolder = mValues.get(mFirstPropertyName); + // mValues should always be non-null + PropertyValuesHolder valuesHolder = mValues[0]; + String oldName = valuesHolder.getPropertyName(); valuesHolder.setPropertyName(propertyName); - mFirstPropertyName = propertyName; + mValuesMap.remove(oldName); + mValuesMap.put(propertyName, valuesHolder); } mPropertyName = propertyName; } @@ -184,8 +183,9 @@ public final class PropertyAnimator extends Animator { @Override void initAnimation() { super.initAnimation(); - for (PropertyValuesHolder valuesHolder : mValues.values()) { - valuesHolder.setupSetterAndGetter(mTarget); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setupSetterAndGetter(mTarget); } } @@ -223,8 +223,9 @@ public final class PropertyAnimator extends Animator { @Override void animateValue(float fraction) { super.animateValue(fraction); - for (PropertyValuesHolder valuesHolder : mValues.values()) { - valuesHolder.setAnimatedValue(mTarget); + int numValues = mValues.length; + for (int i = 0; i < numValues; ++i) { + mValues[i].setAnimatedValue(mTarget); } } } diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 05e0bc108b283..fc829b84cdafa 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -261,11 +261,12 @@ public class PropertyValuesHolder { // Swallow the error and keep trying other variants } } + // If we got here, then no appropriate function was found + Log.e("PropertyValuesHolder", + "Couldn't find setter/getter for property " + mPropertyName + + "with value type "+ mValueType); } - // If we got here, then no appropriate function was found - Log.e("PropertyValuesHolder", - "Couldn't find setter/getter for property " + mPropertyName + - "with value type "+ mValueType); + return returnVal; }