From 21290a62a58581eecd29f4895bb7319a0cb5721a Mon Sep 17 00:00:00 2001 From: George Mount Date: Mon, 22 Jun 2015 13:23:06 -0700 Subject: [PATCH] Suppress Layout during Visibility transitions Bug 21770464 Layout while a View is transitioning out can cause strange behavior during the animation. This CL suppresses the layout during the transition. It also invalidates the parent when it has been removed rather than requesting layout on it. Change-Id: I471243f5beef44d3bbed9ce844e66195dbf4ae10 --- core/java/android/transition/Visibility.java | 43 +++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java index 8b74a1e24a0d4..585fc4e82583a 100644 --- a/core/java/android/transition/Visibility.java +++ b/core/java/android/transition/Visibility.java @@ -504,13 +504,20 @@ public abstract class Visibility extends Transition { private final boolean mIsForcedVisibility; private final View mView; private final int mFinalVisibility; + private final ViewGroup mParent; + private boolean mEnded; boolean mCanceled = false; public DisappearListener(View view, int finalVisibility, boolean isForcedVisibility) { this.mView = view; this.mIsForcedVisibility = isForcedVisibility; this.mFinalVisibility = finalVisibility; + this.mParent = (ViewGroup) view.getParent(); + if (!isForcedVisibility && mParent != null) { + // Prevent a layout from including mView in its calculation. + mParent.suppressLayout(true); + } } @Override @@ -552,13 +559,39 @@ public abstract class Visibility extends Transition { hideViewWhenNotCanceled(); } + @Override + public void onTransitionPause(Transition transition) { + if (mParent != null && !mIsForcedVisibility) { + mParent.suppressLayout(false); + } + } + + @Override + public void onTransitionResume(Transition transition) { + if (mParent != null && !mIsForcedVisibility) { + mParent.suppressLayout(true); + } + } + private void hideViewWhenNotCanceled() { - if (!mCanceled) { - if (mIsForcedVisibility) { - mView.setTransitionAlpha(0); - } else { - mView.setVisibility(mFinalVisibility); + if (!mEnded) { + if (!mCanceled) { + if (mIsForcedVisibility) { + mView.setTransitionAlpha(0); + } else { + // Recreate the parent's display list in case it includes mView. + mView.setTransitionVisibility(mFinalVisibility); + if (mParent != null) { + mParent.invalidate(); + } + } } + if (!mIsForcedVisibility && mParent != null) { + // Layout is allowed now that the View is in its final state + mParent.suppressLayout(false); + } + // Do this only once + mEnded = true; } } }