summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2010-12-13 16:15:53 -0800
committerChet Haase <chet@google.com>2010-12-13 16:15:53 -0800
commite64ea87f966e995f5e1a77f991b9da0ed21ffab0 (patch)
treeda48b90ee05687ab372a68d6d9e4bec6d81fad45 /core/java
parentad3ec1b9cb7885a7c5a18012764d63bdc0cdbb88 (diff)
downloadframeworks_base-e64ea87f966e995f5e1a77f991b9da0ed21ffab0.zip
frameworks_base-e64ea87f966e995f5e1a77f991b9da0ed21ffab0.tar.gz
frameworks_base-e64ea87f966e995f5e1a77f991b9da0ed21ffab0.tar.bz2
Fix artifact with concurrent add/remove LayoutTransitions
There was a bug with LayoutTransitions where if the animations were of different duration (such as in the current status bar clock), it was possible to end up in a bad situation because the previous animation might outlast the new animation, causing the opposite end result from what was expected. The fix was to keep track of the current add/remove animations and to cancel any running ones prior to starting new ones. Change-Id: I884ce33ce0671f6ba6153ee3951c8d14c5ed5714
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/animation/LayoutTransition.java25
1 files changed, 19 insertions, 6 deletions
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index d843737..cb06c89 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -147,13 +147,14 @@ public class LayoutTransition {
private TimeInterpolator mChangingDisappearingInterpolator = new DecelerateInterpolator();
/**
- * This hashmap is used to store the animations that are currently running as part of
+ * These hashmaps are used to store the animations that are currently running as part of
* the transition. The reason for this is that a further layout event should cause
* existing animations to stop where they are prior to starting new animations. So
* we cache all of the current animations in this map for possible cancellation on
* another layout event.
*/
- private HashMap<View, Animator> currentAnimations = new HashMap<View, Animator>();
+ private HashMap<View, Animator> currentChangingAnimations = new HashMap<View, Animator>();
+ private HashMap<View, Animator> currentVisibilityAnimations = new HashMap<View, Animator>();
/**
* This hashmap is used to track the listeners that have been added to the children of
@@ -542,17 +543,17 @@ public class LayoutTransition {
if (child != newView) {
// If there's an animation running on this view already, cancel it
- Animator currentAnimation = currentAnimations.get(child);
+ Animator currentAnimation = currentChangingAnimations.get(child);
if (currentAnimation != null) {
currentAnimation.cancel();
- currentAnimations.remove(child);
+ currentChangingAnimations.remove(child);
}
// Make a copy of the appropriate animation
final Animator anim = baseAnimator.clone();
// Cache the animation in case we need to cancel it later
- currentAnimations.put(child, anim);
+ currentChangingAnimations.put(child, anim);
// Set the target object for the animation
anim.setTarget(child);
@@ -606,7 +607,7 @@ public class LayoutTransition {
}
public void onAnimationEnd(Animator animator) {
if (!canceled) {
- currentAnimations.remove(child);
+ currentChangingAnimations.remove(child);
}
}
});
@@ -640,6 +641,10 @@ public class LayoutTransition {
* @param child The View being added to the ViewGroup.
*/
private void runAppearingTransition(final ViewGroup parent, final View child) {
+ Animator currentAnimation = currentVisibilityAnimations.get(child);
+ if (currentAnimation != null) {
+ currentAnimation.cancel();
+ }
if (mAppearingAnim == null) {
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
@@ -658,12 +663,14 @@ public class LayoutTransition {
if (mListeners != null) {
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd() {
+ currentVisibilityAnimations.remove(child);
for (TransitionListener listener : mListeners) {
listener.endTransition(LayoutTransition.this, parent, child, APPEARING);
}
}
});
}
+ currentVisibilityAnimations.put(child, anim);
anim.start();
}
@@ -674,6 +681,10 @@ public class LayoutTransition {
* @param child The View being removed from the ViewGroup.
*/
private void runDisappearingTransition(final ViewGroup parent, final View child) {
+ Animator currentAnimation = currentVisibilityAnimations.get(child);
+ if (currentAnimation != null) {
+ currentAnimation.cancel();
+ }
if (mDisappearingAnim == null) {
if (mListeners != null) {
for (TransitionListener listener : mListeners) {
@@ -690,6 +701,7 @@ public class LayoutTransition {
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator anim) {
+ currentVisibilityAnimations.remove(child);
for (TransitionListener listener : mListeners) {
listener.endTransition(LayoutTransition.this, parent, child, DISAPPEARING);
}
@@ -699,6 +711,7 @@ public class LayoutTransition {
if (anim instanceof ObjectAnimator) {
((ObjectAnimator) anim).setCurrentPlayTime(0);
}
+ currentVisibilityAnimations.put(child, anim);
anim.start();
}