diff options
| author | 2016-10-27 17:54:59 +0000 | |
|---|---|---|
| committer | 2016-10-27 17:55:03 +0000 | |
| commit | 09c7a38755b43058c8cdf2ee35a3e466b1f302f8 (patch) | |
| tree | 04142fa431572bb76f08562b1b52ace92b8cdfc6 | |
| parent | eb1501ac3f02f6ca45c2ddcfad782bc5af2e442c (diff) | |
| parent | 4fe47117606d39e9b7ab5a7fbf5b0dce753c83ba (diff) | |
Merge "Fix hide fragment transition"
| -rw-r--r-- | core/java/android/app/Fragment.java | 15 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 31 | ||||
| -rw-r--r-- | core/java/android/app/FragmentTransition.java | 33 |
3 files changed, 66 insertions, 13 deletions
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java index 5d1cd3ba8a9c..8124232bd49e 100644 --- a/core/java/android/app/Fragment.java +++ b/core/java/android/app/Fragment.java @@ -2849,6 +2849,17 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene return mAnimationInfo.mEnterTransitionPostponed; } + boolean isHideReplaced() { + if (mAnimationInfo == null) { + return false; + } + return mAnimationInfo.mIsHideReplaced; + } + + void setHideReplaced(boolean replaced) { + ensureAnimationInfo().mIsHideReplaced = replaced; + } + /** * Used internally to be notified when {@link #startPostponedEnterTransition()} has * been called. This listener will only be called once and then be removed from the @@ -2902,7 +2913,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene // be set to null OnStartEnterTransitionListener mStartEnterTransitionListener; - // True if the View was added, and its animation has yet to be run. - boolean mIsNewlyAdded; + // True if the View was hidden, but the transition is handling the hide + boolean mIsHideReplaced; } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 9345a03bb2f2..233fee73f601 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1185,23 +1185,32 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (anim != null) { anim.setTarget(fragment.mView); if (fragment.mHidden) { - // Delay the actual hide operation until the animation finishes, otherwise - // the fragment will just immediately disappear - anim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - animation.removeListener(this); - if (fragment.mView != null) { - fragment.mView.setVisibility(View.GONE); + if (fragment.isHideReplaced()) { + fragment.setHideReplaced(false); + } else { + // Delay the actual hide operation until the animation finishes, otherwise + // the fragment will just immediately disappear + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + animation.removeListener(this); + if (fragment.mView != null) { + fragment.mView.setVisibility(View.GONE); + } } - } - }); + }); + } } setHWLayerAnimListenerIfAlpha(fragment.mView, anim); anim.start(); } else { - final int visibility = fragment.mHidden ? View.GONE : View.VISIBLE; + final int visibility = fragment.mHidden && !fragment.isHideReplaced() + ? View.GONE + : View.VISIBLE; fragment.mView.setVisibility(visibility); + if (fragment.isHideReplaced()) { + fragment.setHideReplaced(false); + } } } if (fragment.mAdded && fragment.mHasMenu && fragment.mMenuVisible) { diff --git a/core/java/android/app/FragmentTransition.java b/core/java/android/app/FragmentTransition.java index 6f5211468b13..d27dff5e2227 100644 --- a/core/java/android/app/FragmentTransition.java +++ b/core/java/android/app/FragmentTransition.java @@ -222,6 +222,7 @@ class FragmentTransition { sharedElementTransition, inFragment, inIsPop); if (transition != null) { + replaceHide(exitTransition, outFragment, exitingViews); transition.setNameOverrides(nameOverrides); scheduleRemoveTargets(transition, enterTransition, enteringViews, exitTransition, exitingViews, @@ -309,6 +310,38 @@ class FragmentTransition { } /** + * Replace hide operations with visibility changes on the exiting views. Instead of making + * the entire fragment's view GONE, make each exiting view INVISIBLE. At the end of the + * transition, make the fragment's view GONE. + */ + private static void replaceHide(Transition exitTransition, Fragment exitingFragment, + final ArrayList<View> exitingViews) { + if (exitingFragment != null && exitTransition != null && exitingFragment.mAdded + && exitingFragment.mHidden && exitingFragment.mHiddenChanged) { + exitingFragment.setHideReplaced(true); + final View fragmentView = exitingFragment.getView(); + final ViewGroup container = exitingFragment.mContainer; + container.getViewTreeObserver().addOnPreDrawListener( + new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + container.getViewTreeObserver().removeOnPreDrawListener(this); + setViewVisibility(exitingViews, View.INVISIBLE); + return true; + } + }); + exitTransition.addListener(new Transition.TransitionListenerAdapter() { + @Override + public void onTransitionEnd(Transition transition) { + transition.removeListener(this); + fragmentView.setVisibility(View.GONE); + setViewVisibility(exitingViews, View.VISIBLE); + } + }); + } + } + + /** * This method is used for fragment transitions for unoptimized transactions to change the * enter and exit transition targets after the call to * {@link TransitionManager#beginDelayedTransition(ViewGroup, Transition)}. The exit transition |