diff options
| -rw-r--r-- | api/current.xml | 342 | ||||
| -rw-r--r-- | core/java/android/animation/AnimatorInflater.java | 38 | ||||
| -rw-r--r-- | core/java/android/animation/AnimatorSet.java | 56 | ||||
| -rw-r--r-- | core/java/android/animation/FloatKeyframeSet.java | 134 | ||||
| -rw-r--r-- | core/java/android/animation/IntKeyframeSet.java | 133 | ||||
| -rw-r--r-- | core/java/android/animation/Keyframe.java | 244 | ||||
| -rw-r--r-- | core/java/android/animation/KeyframeSet.java | 127 | ||||
| -rw-r--r-- | core/java/android/animation/ObjectAnimator.java | 64 | ||||
| -rw-r--r-- | core/java/android/animation/PropertyValuesHolder.java | 252 | ||||
| -rwxr-xr-x | core/java/android/animation/ValueAnimator.java | 110 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 2 |
11 files changed, 857 insertions, 645 deletions
diff --git a/api/current.xml b/api/current.xml index 07f298e..d682155 100644 --- a/api/current.xml +++ b/api/current.xml @@ -17874,7 +17874,7 @@ </class> <class name="Keyframe" extends="java.lang.Object" - abstract="false" + abstract="true" static="false" final="false" deprecated="not deprecated" @@ -17889,137 +17889,156 @@ deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="java.lang.Object"> -</parameter> </constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +<method name="clone" + return="android.animation.Keyframe" + abstract="true" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="java.lang.Float"> -</parameter> -</constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +</method> +<method name="getFraction" + return="float" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="java.lang.Integer"> -</parameter> -</constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +</method> +<method name="getInterpolator" + return="android.animation.TimeInterpolator" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="java.lang.Double"> -</parameter> -</constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +</method> +<method name="getType" + return="java.lang.Class" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="int"> -</parameter> -</constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +</method> +<method name="getValue" + return="java.lang.Object" + abstract="true" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > -<parameter name="fraction" type="float"> -</parameter> -<parameter name="value" type="float"> -</parameter> -</constructor> -<constructor name="Keyframe" - type="android.animation.Keyframe" +</method> +<method name="hasValue" + return="boolean" + abstract="false" + native="false" + synchronized="false" static="false" final="false" deprecated="not deprecated" visibility="public" > +</method> +<method name="ofFloat" + return="android.animation.Keyframe" + abstract="false" + native="false" + synchronized="false" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> <parameter name="fraction" type="float"> </parameter> -<parameter name="value" type="double"> +<parameter name="value" type="float"> </parameter> -</constructor> -<method name="clone" +</method> +<method name="ofFloat" return="android.animation.Keyframe" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="fraction" type="float"> +</parameter> </method> -<method name="getFraction" - return="float" +<method name="ofInt" + return="android.animation.Keyframe" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="fraction" type="float"> +</parameter> +<parameter name="value" type="int"> +</parameter> </method> -<method name="getInterpolator" - return="android.animation.TimeInterpolator" +<method name="ofInt" + return="android.animation.Keyframe" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="fraction" type="float"> +</parameter> </method> -<method name="getType" - return="java.lang.Class" +<method name="ofObject" + return="android.animation.Keyframe" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="fraction" type="float"> +</parameter> +<parameter name="value" type="java.lang.Object"> +</parameter> </method> -<method name="getValue" - return="java.lang.Object" +<method name="ofObject" + return="android.animation.Keyframe" abstract="false" native="false" synchronized="false" - static="false" + static="true" final="false" deprecated="not deprecated" visibility="public" > +<parameter name="fraction" type="float"> +</parameter> </method> <method name="setFraction" return="void" @@ -18049,7 +18068,7 @@ </method> <method name="setValue" return="void" - abstract="false" + abstract="true" native="false" synchronized="false" static="false" @@ -18456,23 +18475,6 @@ visibility="public" > </method> -<method name="ofDouble" - return="android.animation.ObjectAnimator" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="target" type="java.lang.Object"> -</parameter> -<parameter name="propertyName" type="java.lang.String"> -</parameter> -<parameter name="values" type="double..."> -</parameter> -</method> <method name="ofFloat" return="android.animation.ObjectAnimator" abstract="false" @@ -18507,23 +18509,6 @@ <parameter name="values" type="int..."> </parameter> </method> -<method name="ofLong" - return="android.animation.ObjectAnimator" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="target" type="java.lang.Object"> -</parameter> -<parameter name="propertyName" type="java.lang.String"> -</parameter> -<parameter name="values" type="long..."> -</parameter> -</method> <method name="ofObject" return="android.animation.ObjectAnimator" abstract="false" @@ -18626,21 +18611,6 @@ visibility="public" > </method> -<method name="ofDouble" - return="android.animation.PropertyValuesHolder" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="propertyName" type="java.lang.String"> -</parameter> -<parameter name="values" type="double..."> -</parameter> -</method> <method name="ofFloat" return="android.animation.PropertyValuesHolder" abstract="false" @@ -18686,21 +18656,6 @@ <parameter name="values" type="android.animation.Keyframe..."> </parameter> </method> -<method name="ofLong" - return="android.animation.PropertyValuesHolder" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="propertyName" type="java.lang.String"> -</parameter> -<parameter name="values" type="long..."> -</parameter> -</method> <method name="ofObject" return="android.animation.PropertyValuesHolder" abstract="false" @@ -18718,19 +18673,6 @@ <parameter name="values" type="java.lang.Object..."> </parameter> </method> -<method name="setDoubleValues" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="double..."> -</parameter> -</method> <method name="setEvaluator" return="void" abstract="false" @@ -18796,19 +18738,6 @@ <parameter name="values" type="android.animation.Keyframe..."> </parameter> </method> -<method name="setLongValues" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="long..."> -</parameter> -</method> <method name="setObjectValues" return="void" abstract="false" @@ -19083,19 +19012,6 @@ visibility="public" > </method> -<method name="ofDouble" - return="android.animation.ValueAnimator" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="double..."> -</parameter> -</method> <method name="ofFloat" return="android.animation.ValueAnimator" abstract="false" @@ -19122,19 +19038,6 @@ <parameter name="values" type="int..."> </parameter> </method> -<method name="ofLong" - return="android.animation.ValueAnimator" - abstract="false" - native="false" - synchronized="false" - static="true" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="long..."> -</parameter> -</method> <method name="ofObject" return="android.animation.ValueAnimator" abstract="false" @@ -19211,19 +19114,6 @@ <parameter name="playTime" type="long"> </parameter> </method> -<method name="setDoubleValues" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="double..."> -</parameter> -</method> <method name="setDuration" return="android.animation.ValueAnimator" abstract="false" @@ -19302,19 +19192,6 @@ <parameter name="value" type="android.animation.TimeInterpolator"> </parameter> </method> -<method name="setLongValues" - return="void" - abstract="false" - native="false" - synchronized="false" - static="false" - final="false" - deprecated="not deprecated" - visibility="public" -> -<parameter name="values" type="long..."> -</parameter> -</method> <method name="setObjectValues" return="void" abstract="false" @@ -166627,6 +166504,17 @@ visibility="public" > </field> +<field name="NETWORK_TYPE_EHRPD" + type="int" + transient="false" + volatile="false" + value="14" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="NETWORK_TYPE_EVDO_0" type="int" transient="false" @@ -166715,6 +166603,17 @@ visibility="public" > </field> +<field name="NETWORK_TYPE_LTE" + type="int" + transient="false" + volatile="false" + value="13" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="NETWORK_TYPE_UMTS" type="int" transient="false" @@ -166770,6 +166669,17 @@ visibility="public" > </field> +<field name="PHONE_TYPE_SIP" + type="int" + transient="false" + volatile="false" + value="3" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="SIM_STATE_ABSENT" type="int" transient="false" @@ -250796,7 +250706,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -250811,11 +250721,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <parameter name="offset" type="int"> </parameter> -<parameter name="count" type="int"> +<parameter name="byteCount" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -251056,7 +250966,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -251071,11 +250981,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <parameter name="offset" type="int"> </parameter> -<parameter name="length" type="int"> +<parameter name="byteCount" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -253982,7 +253892,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -253997,11 +253907,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <parameter name="offset" type="int"> </parameter> -<parameter name="length" type="int"> +<parameter name="byteCount" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -257802,7 +257712,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -257817,11 +257727,11 @@ deprecated="not deprecated" visibility="public" > -<parameter name="buffer" type="byte[]"> +<parameter name="dst" type="byte[]"> </parameter> <parameter name="offset" type="int"> </parameter> -<parameter name="count" type="int"> +<parameter name="byteCount" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> @@ -283974,9 +283884,9 @@ > <parameter name="uri" type="java.net.URI"> </parameter> -<parameter name="sa" type="java.net.SocketAddress"> +<parameter name="address" type="java.net.SocketAddress"> </parameter> -<parameter name="ioe" type="java.io.IOException"> +<parameter name="failure" type="java.io.IOException"> </parameter> </method> <method name="getDefault" @@ -284075,7 +283985,7 @@ > <parameter name="uri" type="java.net.URI"> </parameter> -<parameter name="conn" type="java.net.URLConnection"> +<parameter name="connection" type="java.net.URLConnection"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java index 4a6c460..b96391a 100644 --- a/core/java/android/animation/AnimatorInflater.java +++ b/core/java/android/animation/AnimatorInflater.java @@ -51,8 +51,6 @@ public class AnimatorInflater { */ 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_LONG = 3; private static final int VALUE_TYPE_COLOR = 4; private static final int VALUE_TYPE_CUSTOM = 5; @@ -242,42 +240,6 @@ public class AnimatorInflater { } break; - case VALUE_TYPE_LONG: { - int valueFrom; - int valueTo; - if (hasFrom) { - valueFrom = a.getInteger(com.android.internal.R.styleable.Animator_valueFrom, 0); - if (hasTo) { - valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0); - anim.setLongValues(valueFrom, valueTo); - } else { - anim.setLongValues(valueFrom); - } - } else { - valueTo = a.getInteger(com.android.internal.R.styleable.Animator_valueTo, 0); - anim.setLongValues(valueTo); - } - } - break; - - case VALUE_TYPE_DOUBLE: { - double valueFrom; - double valueTo; - if (hasFrom) { - valueFrom = a.getFloat(com.android.internal.R.styleable.Animator_valueFrom, 0f); - if (hasTo) { - valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f); - anim.setDoubleValues(valueFrom, valueTo); - } else { - anim.setDoubleValues(valueFrom); - } - } else { - valueTo = a.getFloat(com.android.internal.R.styleable.Animator_valueTo, 0f); - anim.setDoubleValues(valueTo); - } - } - break; - case VALUE_TYPE_CUSTOM: { // TODO: How to get an 'Object' value? float valueFrom; diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java index 8fc45f4..9ba9388 100644 --- a/core/java/android/animation/AnimatorSet.java +++ b/core/java/android/animation/AnimatorSet.java @@ -362,14 +362,18 @@ public final class AnimatorSet extends Animator { // 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 (Node node : mSortedNodes) { + int numSortedNodes = mSortedNodes.size(); + 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 { - for (Dependency dependency : node.dependencies) { + 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)); } @@ -389,7 +393,9 @@ public final class AnimatorSet extends Animator { delayAnim.setDuration(mStartDelay); delayAnim.addListener(new AnimatorListenerAdapter() { public void onAnimationEnd(Animator anim) { - for (Node node : nodesToStart) { + int numNodes = nodesToStart.size(); + for (int i = 0; i < numNodes; ++i) { + Node node = nodesToStart.get(i); node.animation.start(); mPlayingSet.add(node.animation); } @@ -399,8 +405,9 @@ public final class AnimatorSet extends Animator { if (mListeners != null) { ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationStart(this); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); } } } @@ -540,7 +547,9 @@ public final class AnimatorSet extends Animator { return; } Dependency dependencyToRemove = null; - for (Dependency dependency : mNode.tmpDependencies) { + 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 @@ -571,8 +580,9 @@ public final class AnimatorSet extends Animator { public void onAnimationCancel(Animator animation) { if (mPlayingSet.size() == 0) { if (mListeners != null) { - for (AnimatorListener listener : mListeners) { - listener.onAnimationCancel(mAnimatorSet); + int numListeners = mListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mListeners.get(i).onAnimationCancel(mAnimatorSet); } } } @@ -586,8 +596,9 @@ public final class AnimatorSet extends Animator { animNode.done = true; ArrayList<Node> sortedNodes = mAnimatorSet.mSortedNodes; boolean allDone = true; - for (Node node : sortedNodes) { - if (!node.done) { + int numSortedNodes = sortedNodes.size(); + for (int i = 0; i < numSortedNodes; ++i) { + if (!sortedNodes.get(i).done) { allDone = false; break; } @@ -598,8 +609,9 @@ public final class AnimatorSet extends Animator { if (mListeners != null) { ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationEnd(mAnimatorSet); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationEnd(mAnimatorSet); } } } @@ -629,17 +641,23 @@ public final class AnimatorSet extends Animator { if (mNeedsSort) { mSortedNodes.clear(); ArrayList<Node> roots = new ArrayList<Node>(); - for (Node node : mNodes) { + 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) { - for (Node root : roots) { + int numRoots = roots.size(); + for (int i = 0; i < numRoots; ++i) { + Node root = roots.get(i); mSortedNodes.add(root); if (root.nodeDependents != null) { - for (Node node : root.nodeDependents) { + 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); @@ -660,9 +678,13 @@ public final class AnimatorSet extends Animator { // 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 - for (Node node : mNodes) { + int numNodes = mNodes.size(); + for (int i = 0; i < numNodes; ++i) { + Node node = mNodes.get(i); if (node.dependencies != null && node.dependencies.size() > 0) { - for (Dependency dependency : node.dependencies) { + 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>(); } diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java new file mode 100644 index 0000000..6fad4a68 --- /dev/null +++ b/core/java/android/animation/FloatKeyframeSet.java @@ -0,0 +1,134 @@ +/* + * 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.animation.Keyframe.FloatKeyframe; + +import java.util.ArrayList; + +/** + * 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 subclasses for + * int, long, and double, 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> + */ +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 TimeInterpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + fraction * (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 TimeInterpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + fraction * (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 TimeInterpolator 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 + fraction * (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/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java new file mode 100644 index 0000000..14a4e3a --- /dev/null +++ b/core/java/android/animation/IntKeyframeSet.java @@ -0,0 +1,133 @@ +/* + * 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.animation.Keyframe.IntKeyframe; + +import java.util.ArrayList; + +/** + * 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 subclasses for + * float, long, and double, 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> + */ +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 TimeInterpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + (int)(fraction * (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 TimeInterpolator interpolator = nextKeyframe.getInterpolator(); + if (interpolator != null) { + fraction = interpolator.getInterpolation(fraction); + } + float intervalFraction = (fraction - prevFraction) / (nextFraction - prevFraction); + return mEvaluator == null ? + prevValue + (int)(fraction * (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 TimeInterpolator 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)(fraction * (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/core/java/android/animation/Keyframe.java b/core/java/android/animation/Keyframe.java index f9a4f3c..e98719a 100644 --- a/core/java/android/animation/Keyframe.java +++ b/core/java/android/animation/Keyframe.java @@ -23,23 +23,27 @@ package android.animation; * 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> */ -public class Keyframe implements Cloneable { +public abstract class Keyframe implements Cloneable { /** * The time at which mValue will hold true. */ - private float mFraction; - - /** - * The value of the animation at the time mFraction. - */ - private Object mValue; + 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. */ - private Class mValueType; + Class mValueType; /** * The optional time interpolator for the interval preceding this keyframe. A null interpolator @@ -48,23 +52,11 @@ public class Keyframe implements Cloneable { private TimeInterpolator mInterpolator = null; /** - * Private constructor, called from the public constructors with the additional - * <code>valueType</code> parameter. - * - * @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. - * @param valueType The type of the <code>value</code> object. This is used by the - * {@link #getValue()} functionm, which is queried by {@link ValueAnimator} to determine - * the type of {@link TypeEvaluator} to use to interpolate between values. + * 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. */ - private Keyframe(float fraction, Object value, Class valueType) { - mFraction = fraction; - mValue = value; - mValueType = valueType; - } + boolean mHasValue = false; /** * Constructs a Keyframe object with the given time and value. The time defines the @@ -78,28 +70,28 @@ public class Keyframe implements Cloneable { * the time in this keyframe, and the the value animated from as the time passes the time in * this keyframe. */ - public Keyframe(float fraction, Object value) { - this(fraction, value, (value != null) ? value.getClass() : Object.class); + public static Keyframe ofInt(float fraction, int value) { + return new IntKeyframe(fraction, value); } /** - * Constructs a Keyframe object with the given time and float value. The time defines the + * 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. - * @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 Keyframe(float fraction, Float value) { - this(fraction, value, Float.class); + public static Keyframe ofInt(float fraction) { + return new IntKeyframe(fraction); } /** - * Constructs a Keyframe object with the given time and integer value. The time defines the + * 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. @@ -110,28 +102,28 @@ public class Keyframe implements Cloneable { * the time in this keyframe, and the the value animated from as the time passes the time in * this keyframe. */ - public Keyframe(float fraction, Integer value) { - this(fraction, value, Integer.class); + public static Keyframe ofFloat(float fraction, float value) { + return new FloatKeyframe(fraction, value); } /** - * Constructs a Keyframe object with the given time and double value. The time defines the + * 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. - * @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 Keyframe(float fraction, Double value) { - this(fraction, value, Double.class); + public static Keyframe ofFloat(float fraction) { + return new FloatKeyframe(fraction); } /** - * Constructs a Keyframe object with the given time and integer value. The time defines the + * 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. @@ -142,40 +134,35 @@ public class Keyframe implements Cloneable { * the time in this keyframe, and the the value animated from as the time passes the time in * this keyframe. */ - public Keyframe(float fraction, int value) { - this(fraction, value, int.class); + public static Keyframe ofObject(float fraction, Object value) { + return new ObjectKeyframe(fraction, value); } /** - * Constructs a Keyframe object with the given time and float value. The time defines the + * 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. - * @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 Keyframe(float fraction, float value) { - this(fraction, value, float.class); + public static Keyframe ofObject(float fraction) { + return new ObjectKeyframe(fraction, null); } /** - * Constructs a Keyframe object with the given time and double 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. + * 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. * - * @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. + * @return boolean Whether this object has a value assigned. */ - public Keyframe(float fraction, double value) { - this(fraction, value, double.class); + public boolean hasValue() { + return mHasValue; } /** @@ -183,18 +170,14 @@ public class Keyframe implements Cloneable { * * @return The value for this Keyframe. */ - public Object getValue() { - return mValue; - } + public abstract Object getValue(); /** * Sets the value for this Keyframe. * * @param value value for this Keyframe. */ - public void setValue(Object value) { - mValue = value; - } + public abstract void setValue(Object value); /** * Gets the time for this keyframe, as a fraction of the overall animation duration. @@ -248,9 +231,128 @@ public class Keyframe implements Cloneable { } @Override - public Keyframe clone() { - Keyframe kfClone = new Keyframe(mFraction, mValue, mValueType); - kfClone.setInterpolator(mInterpolator); - return kfClone; + 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/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java index 2242462..fa61b71 100644 --- a/core/java/android/animation/KeyframeSet.java +++ b/core/java/android/animation/KeyframeSet.java @@ -18,6 +18,9 @@ package android.animation; import java.util.ArrayList; import java.util.Arrays; +import android.animation.Keyframe.IntKeyframe; +import android.animation.Keyframe.FloatKeyframe; +import android.animation.Keyframe.ObjectKeyframe; /** * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate @@ -26,12 +29,14 @@ import java.util.Arrays; */ class KeyframeSet { - private int mNumKeyframes; + int mNumKeyframes; Keyframe mFirstKeyframe; Keyframe mLastKeyframe; TimeInterpolator 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; @@ -44,80 +49,106 @@ class KeyframeSet { public static KeyframeSet ofInt(int... values) { int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; + IntKeyframe keyframes[] = new IntKeyframe[Math.max(numKeyframes,2)]; if (numKeyframes == 1) { - keyframes[0] = new Keyframe(0f, (Object) null); - keyframes[1] = new Keyframe(1f, values[0]); + keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f); + keyframes[1] = (IntKeyframe) Keyframe.ofInt(1f, values[0]); } else { - keyframes[0] = new Keyframe(0f, values[0]); + keyframes[0] = (IntKeyframe) Keyframe.ofInt(0f, values[0]); for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = new Keyframe((float) i / (numKeyframes - 1), values[i]); + keyframes[i] = (IntKeyframe) Keyframe.ofInt((float) i / (numKeyframes - 1), values[i]); } } - return new KeyframeSet(keyframes); + return new IntKeyframeSet(keyframes); } public static KeyframeSet ofFloat(float... values) { int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; + FloatKeyframe keyframes[] = new FloatKeyframe[Math.max(numKeyframes,2)]; if (numKeyframes == 1) { - keyframes[0] = new Keyframe(0f, (Object) null); - keyframes[1] = new Keyframe(1f, values[0]); + keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f); + keyframes[1] = (FloatKeyframe) Keyframe.ofFloat(1f, values[0]); } else { - keyframes[0] = new Keyframe(0f, values[0]); + keyframes[0] = (FloatKeyframe) Keyframe.ofFloat(0f, values[0]); for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = new Keyframe((float) i / (numKeyframes - 1), values[i]); + keyframes[i] = (FloatKeyframe) Keyframe.ofFloat((float) i / (numKeyframes - 1), values[i]); } } - return new KeyframeSet(keyframes); + return new FloatKeyframeSet(keyframes); } - public static KeyframeSet ofDouble(double... values) { - int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; - if (numKeyframes == 1) { - keyframes[0] = new Keyframe(0f, (Object) null); - keyframes[1] = new Keyframe(1f, values[0]); - } else { - keyframes[0] = new Keyframe(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = new Keyframe((float) i / (numKeyframes - 1), values[i]); + 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; } } - return new KeyframeSet(keyframes); - } - - public static KeyframeSet ofLong(long... values) { - int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; - if (numKeyframes == 1) { - keyframes[0] = new Keyframe(0f, (Object) null); - keyframes[1] = new Keyframe(1f, values[0]); - } else { - keyframes[0] = new Keyframe(0f, values[0]); - for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = new Keyframe((float) i / (numKeyframes - 1), values[i]); + 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); } - return new KeyframeSet(keyframes); } public static KeyframeSet ofObject(Object... values) { int numKeyframes = values.length; - Keyframe keyframes[] = new Keyframe[Math.max(numKeyframes,2)]; + ObjectKeyframe keyframes[] = new ObjectKeyframe[Math.max(numKeyframes,2)]; if (numKeyframes == 1) { - keyframes[0] = new Keyframe(0f, (Object) null); - keyframes[1] = new Keyframe(1f, values[0]); + keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f); + keyframes[1] = (ObjectKeyframe) Keyframe.ofObject(1f, values[0]); } else { - keyframes[0] = new Keyframe(0f, values[0]); + keyframes[0] = (ObjectKeyframe) Keyframe.ofObject(0f, values[0]); for (int i = 1; i < numKeyframes; ++i) { - keyframes[i] = new Keyframe((float) i / (numKeyframes - 1), values[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 @@ -127,20 +158,18 @@ class KeyframeSet { * just using the two keyframes at the appropriate end when the value is outside those bounds. * * @param fraction The elapsed fraction of the animation - * @param evaluator The type evaluator to use when calculating the interpolated values. * @return The animated value. */ - public Object getValue(float fraction, TypeEvaluator evaluator) { + 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 evaluator.evaluate(fraction, mFirstKeyframe.getValue(), + return mEvaluator.evaluate(fraction, mFirstKeyframe.getValue(), mLastKeyframe.getValue()); } - if (fraction <= 0f) { final Keyframe nextKeyframe = mKeyframes.get(1); final TimeInterpolator interpolator = nextKeyframe.getInterpolator(); @@ -150,7 +179,7 @@ class KeyframeSet { final float prevFraction = mFirstKeyframe.getFraction(); float intervalFraction = (fraction - prevFraction) / (nextKeyframe.getFraction() - prevFraction); - return evaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(), + return mEvaluator.evaluate(intervalFraction, mFirstKeyframe.getValue(), nextKeyframe.getValue()); } else if (fraction >= 1f) { final Keyframe prevKeyframe = mKeyframes.get(mNumKeyframes - 2); @@ -161,7 +190,7 @@ class KeyframeSet { final float prevFraction = prevKeyframe.getFraction(); float intervalFraction = (fraction - prevFraction) / (mLastKeyframe.getFraction() - prevFraction); - return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(), + return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), mLastKeyframe.getValue()); } Keyframe prevKeyframe = mFirstKeyframe; @@ -175,7 +204,7 @@ class KeyframeSet { final float prevFraction = prevKeyframe.getFraction(); float intervalFraction = (fraction - prevFraction) / (nextKeyframe.getFraction() - prevFraction); - return evaluator.evaluate(intervalFraction, prevKeyframe.getValue(), + return mEvaluator.evaluate(intervalFraction, prevKeyframe.getValue(), nextKeyframe.getValue()); } prevKeyframe = nextKeyframe; diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java index 5b8c91d..c898ae3 100644 --- a/core/java/android/animation/ObjectAnimator.java +++ b/core/java/android/animation/ObjectAnimator.java @@ -175,48 +175,6 @@ public final class ObjectAnimator extends ValueAnimator { } /** - * Constructs and returns an ObjectAnimator that animates between long 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 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 A ValueAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofLong(Object target, String propertyName, long... values) { - ObjectAnimator anim = new ObjectAnimator(target, propertyName); - anim.setLongValues(values); - return anim; - } - - /** - * Constructs and returns an ObjectAnimator that animates between double 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 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 A ValueAnimator object that is set up to animate between the given values. - */ - public static ObjectAnimator ofDouble(Object target, String propertyName, double... values) { - ObjectAnimator anim = new ObjectAnimator(target, propertyName); - anim.setDoubleValues(values); - return anim; - } - - /** * A constructor that takes <code>PropertyValueHolder</code> values. This constructor 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 @@ -287,28 +245,6 @@ public final class ObjectAnimator extends ValueAnimator { } @Override - public void setDoubleValues(double... 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 - setValues(PropertyValuesHolder.ofDouble(mPropertyName, values)); - } else { - super.setDoubleValues(values); - } - } - - @Override - public void setLongValues(long... 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 - setValues(PropertyValuesHolder.ofLong(mPropertyName, values)); - } else { - super.setLongValues(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 diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 0f759f1..39754b0 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -17,6 +17,8 @@ package android.animation; import android.util.Log; +import android.animation.Keyframe.IntKeyframe; +import android.animation.Keyframe.FloatKeyframe; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -45,7 +47,7 @@ public class PropertyValuesHolder implements Cloneable { * property can be manually set via setSetter(). Otherwise, it is automatically * derived when the animation starts in setupSetterAndGetter() if using ObjectAnimator. */ - private Method mSetter = null; + Method mSetter = null; /** * The getter function, if needed. ObjectAnimator hands off this functionality to @@ -60,12 +62,12 @@ public class PropertyValuesHolder implements Cloneable { * The type of values supplied. This information is used both in deriving the setter/getter * functions and in deriving the type of TypeEvaluator. */ - private Class mValueType; + Class mValueType; /** * The set of keyframes (time/value pairs) that define this animation. */ - private KeyframeSet mKeyframeSet = null; + KeyframeSet mKeyframeSet = null; // type evaluators for the three primitive types handled by this implementation @@ -100,7 +102,7 @@ public class PropertyValuesHolder implements Cloneable { private ReentrantReadWriteLock propertyMapLock = new ReentrantReadWriteLock(); // Used to pass single value to varargs parameter in setter invocation - private Object[] mTmpValueArray = new Object[1]; + Object[] mTmpValueArray = new Object[1]; /** * The type evaluator used to calculate the animated values. This evaluator is determined @@ -133,8 +135,7 @@ public class PropertyValuesHolder implements Cloneable { * @return PropertyValuesHolder The constructed PropertyValuesHolder object. */ public static PropertyValuesHolder ofInt(String propertyName, int... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setIntValues(values); + PropertyValuesHolder pvh = new IntPropertyValuesHolder(propertyName, values); return pvh; } @@ -146,34 +147,7 @@ public class PropertyValuesHolder implements Cloneable { * @return PropertyValuesHolder The constructed PropertyValuesHolder object. */ public static PropertyValuesHolder ofFloat(String propertyName, float... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setFloatValues(values); - return pvh; - } - - /** - * Constructs and returns a PropertyValuesHolder with a given property name and - * set of double 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 ofDouble(String propertyName, double... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setDoubleValues(values); - return pvh; - } - - /** - * Constructs and returns a PropertyValuesHolder with a given property name and - * set of long 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 ofLong(String propertyName, long... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setLongValues(values); + PropertyValuesHolder pvh = new FloatPropertyValuesHolder(propertyName, values); return pvh; } @@ -218,9 +192,18 @@ public class PropertyValuesHolder implements Cloneable { * @param values The set of values to animate between. */ public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe... values) { - PropertyValuesHolder pvh = new PropertyValuesHolder(propertyName); - pvh.setKeyframes(values); - return pvh; + 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 = ((Keyframe)values[0]).getType(); + return pvh; + } } /** @@ -262,44 +245,6 @@ public class PropertyValuesHolder implements Cloneable { } /** - * Set the animated values for this object to this set of doubles. - * 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 either - * derived automatically from <code>propertyName</code> or set explicitly via - * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * - * @param values One or more values that the animation will animate between. - */ - public void setDoubleValues(double... values) { - mValueType = double.class; - mKeyframeSet = KeyframeSet.ofDouble(values); - } - - /** - * Set the animated values for this object to this set of longs. - * 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 either - * derived automatically from <code>propertyName</code> or set explicitly via - * {@link #setGetter(java.lang.reflect.Method)}, since otherwise PropertyValuesHolder has - * no way of determining what the value should be. - * - * @param values One or more values that the animation will animate between. - */ - public void setLongValues(long... values) { - mValueType = long.class; - mKeyframeSet = KeyframeSet.ofLong(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. @@ -466,7 +411,7 @@ public class PropertyValuesHolder implements Cloneable { setupSetter(targetClass); } for (Keyframe kf : mKeyframeSet.mKeyframes) { - if (kf.getValue() == null) { + if (!kf.hasValue()) { if (mGetter == null) { setupGetter(targetClass); } @@ -528,14 +473,18 @@ public class PropertyValuesHolder implements Cloneable { @Override public PropertyValuesHolder clone() { - ArrayList<Keyframe> keyframes = mKeyframeSet.mKeyframes; - int numKeyframes = mKeyframeSet.mKeyframes.size(); - Keyframe[] newKeyframes = new Keyframe[numKeyframes]; - for (int i = 0; i < numKeyframes; ++i) { - newKeyframes[i] = keyframes.get(i).clone(); + try { + PropertyValuesHolder newPVH = (PropertyValuesHolder) super.clone(); + newPVH.mPropertyName = mPropertyName; + newPVH.mKeyframeSet = mKeyframeSet.clone(); + newPVH.mEvaluator = mEvaluator; + return newPVH; + } catch (CloneNotSupportedException e) { + // won't reach here + return null; } - return PropertyValuesHolder.ofKeyframe(mPropertyName, newKeyframes); } + /** * 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 @@ -546,7 +495,7 @@ public class PropertyValuesHolder implements Cloneable { void setAnimatedValue(Object target) { if (mSetter != null) { try { - mTmpValueArray[0] = mAnimatedValue; + mTmpValueArray[0] = getAnimatedValue(); mSetter.invoke(target, mTmpValueArray); } catch (InvocationTargetException e) { Log.e("PropertyValuesHolder", e.toString()); @@ -562,9 +511,16 @@ public class PropertyValuesHolder implements Cloneable { */ void init() { if (mEvaluator == null) { - mEvaluator = (mValueType == int.class || mValueType == Integer.class) ? sIntEvaluator : - (mValueType == double.class || mValueType == Double.class) ? sDoubleEvaluator : - sFloatEvaluator; + // We already handle int, float, long, double 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 + // evaulator if one has been set on this class + mKeyframeSet.setEvaluator(mEvaluator); } } @@ -578,8 +534,9 @@ public class PropertyValuesHolder implements Cloneable { * and Integer) are correctly interpolated; all other types require setting a TypeEvaluator. * @param evaluator */ - public void setEvaluator(TypeEvaluator evaluator) { + public void setEvaluator(TypeEvaluator evaluator) { mEvaluator = evaluator; + mKeyframeSet.setEvaluator(evaluator); } /** @@ -587,11 +544,9 @@ public class PropertyValuesHolder implements Cloneable { * this PropertyValuesHolder object. This function is called by ValueAnimator.animateValue(). * * @param fraction The elapsed, interpolated fraction of the animation. - * @return The calculated value at this point in the animation. */ - Object calculateValue(float fraction) { - mAnimatedValue = mKeyframeSet.getValue(fraction, mEvaluator); - return mAnimatedValue; + void calculateValue(float fraction) { + mAnimatedValue = mKeyframeSet.getValue(fraction); } /** @@ -694,4 +649,119 @@ public class PropertyValuesHolder implements Cloneable { Object getAnimatedValue() { return mAnimatedValue; } + + static class IntPropertyValuesHolder extends PropertyValuesHolder { + + IntKeyframeSet mIntKeyframeSet; + int mIntAnimatedValue; + + public IntPropertyValuesHolder(String propertyName, IntKeyframeSet keyframeSet) { + super(propertyName); + mValueType = int.class; + mKeyframeSet = keyframeSet; + mIntKeyframeSet = (IntKeyframeSet) mKeyframeSet; + } + + public IntPropertyValuesHolder(String propertyName, int... values) { + super(propertyName); + 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 (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()); + } + } + } + } + + static class FloatPropertyValuesHolder extends PropertyValuesHolder { + + FloatKeyframeSet mFloatKeyframeSet; + float mFloatAnimatedValue; + + public FloatPropertyValuesHolder(String propertyName, FloatKeyframeSet keyframeSet) { + super(propertyName); + mValueType = float.class; + mKeyframeSet = keyframeSet; + mFloatKeyframeSet = (FloatKeyframeSet) mKeyframeSet; + } + + public FloatPropertyValuesHolder(String propertyName, float... values) { + super(propertyName); + 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 (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()); + } + } + } + + } }
\ No newline at end of file diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index a0b70b5..b021e75 100755 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -297,40 +297,6 @@ public class ValueAnimator extends Animator { } /** - * Constructs and returns a ValueAnimator that animates between double 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 ofDouble(double... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setDoubleValues(values); - return anim; - } - - /** - * Constructs and returns a ValueAnimator that animates between long 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 ofLong(long... values) { - ValueAnimator anim = new ValueAnimator(); - anim.setLongValues(values); - return anim; - } - - /** * Constructs and returns a ValueAnimator that animates between the values * specified in the PropertyValuesHolder objects. * @@ -425,62 +391,6 @@ public class ValueAnimator extends Animator { } /** - * Sets long 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 setLongValues(long... values) { - if (values == null || values.length == 0) { - return; - } - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofLong("", values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setLongValues(values); - } - // New property/values/target should cause re-initialization prior to starting - mInitialized = false; - } - - /** - * Sets double 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 setDoubleValues(double... values) { - if (values == null || values.length == 0) { - return; - } - if (mValues == null || mValues.length == 0) { - setValues(new PropertyValuesHolder[]{PropertyValuesHolder.ofDouble("", values)}); - } else { - PropertyValuesHolder valuesHolder = mValues[0]; - valuesHolder.setDoubleValues(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 @@ -968,8 +878,9 @@ public class ValueAnimator extends Animator { if (mListeners != null) { ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationStart(this); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); } } // This sets the initial value of the animation, prior to actually starting it running @@ -1059,8 +970,9 @@ public class ValueAnimator extends Animator { if (mListeners != null) { ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationEnd(this); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationEnd(this); } } } @@ -1077,8 +989,9 @@ public class ValueAnimator extends Animator { // just for delayed animations ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); - for (AnimatorListener listener : tmpListeners) { - listener.onAnimationStart(this); + int numListeners = tmpListeners.size(); + for (int i = 0; i < numListeners; ++i) { + tmpListeners.get(i).onAnimationStart(this); } } } @@ -1147,8 +1060,9 @@ public class ValueAnimator extends Animator { if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { // Time to repeat if (mListeners != null) { - for (AnimatorListener listener : mListeners) { - listener.onAnimationRepeat(this); + int numListeners = mListeners.size(); + for (int i = 0; i < numListeners; ++i) { + mListeners.get(i).onAnimationRepeat(this); } } ++mCurrentIteration; diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index a9f0780..7276044 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8288,7 +8288,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility (ArrayList<OnLayoutChangeListener>) mOnLayoutChangeListeners.clone(); int numListeners = listenersCopy.size(); for (int i = 0; i < numListeners; ++i) { - listenersCopy.get(i).onLayoutChange(this, l, r, t, b, oldL, oldT, oldR, oldB); + listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB); } } } |
