diff options
author | Chet Haase <chet@google.com> | 2011-02-25 11:35:17 -0800 |
---|---|---|
committer | Chet Haase <chet@google.com> | 2011-02-25 12:44:42 -0800 |
commit | ba592d200390d89723682f1a7e40d308d7804b36 (patch) | |
tree | 328e9d7ed87e0316dfba4c6fe075f1e8ccdaf653 | |
parent | 7ad9eb69c45fae0712f767a4b70f670113da92d9 (diff) | |
download | frameworks_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.java | 67 |
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); |