summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2011-02-25 11:35:17 -0800
committerChet Haase <chet@google.com>2011-02-25 12:44:42 -0800
commitba592d200390d89723682f1a7e40d308d7804b36 (patch)
tree328e9d7ed87e0316dfba4c6fe075f1e8ccdaf653
parent7ad9eb69c45fae0712f767a4b70f670113da92d9 (diff)
downloadframeworks_base-ba592d200390d89723682f1a7e40d308d7804b36.zip
frameworks_base-ba592d200390d89723682f1a7e40d308d7804b36.tar.gz
frameworks_base-ba592d200390d89723682f1a7e40d308d7804b36.tar.bz2
ViewPropertyAnimator cancels prior animations
The initial approach of VPA was to cancel previous animations on the same exact set of properties. This worked in most cases, but if the new animation had a different set of properties (like animating alpha, x, and y instead of just x and y), then there was a possible artifact as the old animation continued to run in the background and could show the button in the wrong location as a result. The new approach is to search all running animations for a property when a new animation is requested on it and to remove that property from the list of properties being animated by that previous animation. The prior animations continue to run, but will no longer update that property, which will now be controlled solely by the new animation requested. Change-Id: Ib35d54a5e91be0a1310725be6e2acbaa6ead4a4e
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java67
1 files changed, 49 insertions, 18 deletions
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index cc00f94..27e7db1 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -143,10 +143,36 @@ public class ViewPropertyAnimator {
private static class PropertyBundle {
int mPropertyMask;
ArrayList<NameValuesHolder> mNameValuesHolder;
+
PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
mPropertyMask = propertyMask;
mNameValuesHolder = nameValuesHolder;
}
+
+ /**
+ * Removes the given property from being animated as a part of this
+ * PropertyBundle. If the property was a part of this bundle, it returns
+ * true to indicate that it was, in fact, canceled. This is an indication
+ * to the caller that a cancellation actually occurred.
+ *
+ * @param propertyConstant The property whose cancellation is requested.
+ * @return true if the given property is a part of this bundle and if it
+ * has therefore been canceled.
+ */
+ boolean cancel(int propertyConstant) {
+ if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
+ int count = mNameValuesHolder.size();
+ for (int i = 0; i < count; ++i) {
+ NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
+ if (nameValuesHolder.mNameConstant == propertyConstant) {
+ mNameValuesHolder.remove(i);
+ mPropertyMask &= ~propertyConstant;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
/**
@@ -508,24 +534,6 @@ public class ViewPropertyAnimator {
NameValuesHolder nameValuesHolder = nameValueList.get(i);
propertyMask |= nameValuesHolder.mNameConstant;
}
- // First, cancel any running animation on the same property set
- if (mAnimatorMap.size() > 0) {
- Animator animatorToCancel = null;
- Set<Animator> animatorSet = mAnimatorMap.keySet();
- for (Animator runningAnim : animatorSet) {
- PropertyBundle bundle = mAnimatorMap.get(runningAnim);
- if (bundle.mPropertyMask == propertyMask) {
- // There can be only one such duplicate, because that animation would
- // have caused previous ones to cancel prior to starting. So break when we
- // find one.
- animatorToCancel = runningAnim;
- break;
- }
- }
- if (animatorToCancel != null) {
- animatorToCancel.cancel();
- }
- }
mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
animator.addUpdateListener(mAnimatorEventListener);
animator.addListener(mAnimatorEventListener);
@@ -578,6 +586,29 @@ public class ViewPropertyAnimator {
* @param byValue The amount by which the property will change
*/
private void animatePropertyBy(int constantName, float fromValue, float byValue) {
+ // First, cancel any existing animations on this property
+ if (mAnimatorMap.size() > 0) {
+ Animator animatorToCancel = null;
+ Set<Animator> animatorSet = mAnimatorMap.keySet();
+ for (Animator runningAnim : animatorSet) {
+ PropertyBundle bundle = mAnimatorMap.get(runningAnim);
+ if (bundle.cancel(constantName)) {
+ // property was canceled - cancel the animation if it's now empty
+ // Note that it's safe to break out here because every new animation
+ // on a property will cancel a previous animation on that property, so
+ // there can only ever be one such animation running.
+ if (bundle.mPropertyMask == NONE) {
+ // the animation is not longer changing animthing - cancel it
+ animatorToCancel = runningAnim;
+ break;
+ }
+ }
+ }
+ if (animatorToCancel != null) {
+ animatorToCancel.cancel();
+ }
+ }
+
float startValue = getValue(constantName);
NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
mPendingAnimations.add(nameValuePair);