summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2011-01-12 16:20:16 -0800
committerChet Haase <chet@google.com>2011-01-12 18:14:40 -0800
commit9c0874408cfc6f6f4e4561973ca5ae52a5982db7 (patch)
tree6f600e648ac181bcbebb268d7e2be1a39e9dceb5 /core/java/android
parente9739d09cb53fd05cc9229049b3d54c7f6816450 (diff)
Supress layout requests while a LayoutTransition is running.
LayoutTransition works by animating layout-related properties (left, right, top, and bottom). This works great when that animation is the only thing affecting the layout of the UI. But if there are other things happening in the application that cause layout to run on that container or in its parent hierarchy, this can cause the layout properties on its children to get mis-set during the middle of the transition. This results in artifacts like animating objects jumping to locations where they would be were there no animation running. The fix is to supress layout requests on that container (and its children) until the transition is complete (then issue a layout request on the container to make sure that the container has the correct layout data) Change-Id: I15bf0423a11409f854076f86099233db7fe4edc0
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/animation/LayoutTransition.java52
-rw-r--r--core/java/android/view/View.java7
-rw-r--r--core/java/android/view/ViewGroup.java23
3 files changed, 65 insertions, 17 deletions
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index d534163725b9..e405df5d513a 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -553,9 +553,6 @@ public class LayoutTransition {
// Make a copy of the appropriate animation
final Animator anim = baseAnimator.clone();
- // Cache the animation in case we need to cancel it later
- currentChangingAnimations.put(child, anim);
-
// Set the target object for the animation
anim.setTarget(child);
@@ -586,6 +583,9 @@ public class LayoutTransition {
anim.setStartDelay(startDelay);
anim.setDuration(duration);
+ // Cache the animation in case we need to cancel it later
+ currentChangingAnimations.put(child, anim);
+
if (anim instanceof ObjectAnimator) {
((ObjectAnimator) anim).setCurrentPlayTime(0);
}
@@ -658,6 +658,27 @@ public class LayoutTransition {
}
/**
+ * Returns true if animations are running which animate layout-related properties. This
+ * essentially means that either CHANGE_APPEARING or CHANGE_DISAPPEARING animations
+ * are running, since these animations operate on layout-related properties.
+ *
+ * @return true if CHANGE_APPEARING or CHANGE_DISAPPEARING animations are currently
+ * running.
+ */
+ public boolean isChangingLayout() {
+ return (currentChangingAnimations.size() > 0);
+ }
+
+ /**
+ * Returns true if any of the animations in this transition are currently running.
+ *
+ * @return true if any animations in the transition are running.
+ */
+ public boolean isRunning() {
+ return (currentChangingAnimations.size() > 0 || currentVisibilityAnimations.size() > 0);
+ }
+
+ /**
* This method runs the animation that makes an added item appear.
*
* @param parent The ViewGroup to which the View is being added.
@@ -842,28 +863,31 @@ public class LayoutTransition {
public interface TransitionListener {
/**
- * This event is sent to listeners when an APPEARING or DISAPPEARING transition
- * begins.
+ * This event is sent to listeners when any type of transition animation begins.
*
* @param transition The LayoutTransition sending out the event.
* @param container The ViewGroup on which the transition is playing.
- * @param view The View object being added or removed from its parent.
- * @param transitionType The type of transition that is beginning, either
- * {@link android.animation.LayoutTransition#APPEARING} or
- * {@link android.animation.LayoutTransition#DISAPPEARING}.
+ * @param view The View object being affected by the transition animation.
+ * @param transitionType The type of transition that is beginning,
+ * {@link android.animation.LayoutTransition#APPEARING},
+ * {@link android.animation.LayoutTransition#DISAPPEARING},
+ * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or
+ * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}.
*/
public void startTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType);
/**
- * This event is sent to listeners when an APPEARING or DISAPPEARING transition ends.
+ * This event is sent to listeners when any type of transition animation ends.
*
* @param transition The LayoutTransition sending out the event.
* @param container The ViewGroup on which the transition is playing.
- * @param view The View object being added or removed from its parent.
- * @param transitionType The type of transition that is ending, either
- * {@link android.animation.LayoutTransition#APPEARING} or
- * {@link android.animation.LayoutTransition#DISAPPEARING}.
+ * @param view The View object being affected by the transition animation.
+ * @param transitionType The type of transition that is ending,
+ * {@link android.animation.LayoutTransition#APPEARING},
+ * {@link android.animation.LayoutTransition#DISAPPEARING},
+ * {@link android.animation.LayoutTransition#CHANGE_APPEARING}, or
+ * {@link android.animation.LayoutTransition#CHANGE_DISAPPEARING}.
*/
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20b3b4611aab..45c35f038c5d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -8883,11 +8883,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* (The first is measuring). In this phase, each parent calls
* layout on all of its children to position them.
* This is typically done using the child measurements
- * that were stored in the measure pass().
+ * that were stored in the measure pass().</p>
*
+ * <p>Derived classes should not override this method.
* Derived classes with children should override
* onLayout. In that method, they should
- * call layout on each of their children.
+ * call layout on each of their children.</p>
*
* @param l Left position, relative to parent
* @param t Top position, relative to parent
@@ -8895,7 +8896,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
* @param b Bottom position, relative to parent
*/
@SuppressWarnings({"unchecked"})
- public final void layout(int l, int t, int r, int b) {
+ public void layout(int l, int t, int r, int b) {
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index ed5eed159f0d..d58604329336 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -318,6 +318,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private View[] mChildren;
// Number of valid children in the mChildren array, the rest should be null or not
// considered as children
+
+ private boolean mLayoutSuppressed = false;
+
private int mChildrenCount;
private static final int ARRAY_INITIAL_CAPACITY = 12;
@@ -1828,6 +1831,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// first send it an ACTION_CANCEL motion event.
cancelAndClearTouchTargets(null);
+ // In case view is detached while transition is running
+ mLayoutSuppressed = false;
+
final int count = mChildrenCount;
final View[] children = mChildren;
for (int i = 0; i < count; i++) {
@@ -3622,6 +3628,19 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* {@inheritDoc}
*/
@Override
+ public final void layout(int l, int t, int r, int b) {
+ if (mTransition == null || !mTransition.isChangingLayout()) {
+ super.layout(l, t, r, b);
+ } else {
+ // record the fact that we noop'd it; request layout when transition finishes
+ mLayoutSuppressed = true;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
protected abstract void onLayout(boolean changed,
int l, int t, int r, int b);
@@ -4306,6 +4325,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
@Override
public void endTransition(LayoutTransition transition, ViewGroup container,
View view, int transitionType) {
+ if (mLayoutSuppressed && !transition.isChangingLayout()) {
+ requestLayout();
+ mLayoutSuppressed = false;
+ }
if (transitionType == LayoutTransition.DISAPPEARING && mTransitioningViews != null) {
endViewTransition(view);
}