Loading core/java/android/app/Fragment.java +13 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } } core/java/android/app/FragmentManager.java +20 −11 Original line number Diff line number Diff line Loading @@ -1185,6 +1185,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (anim != null) { anim.setTarget(fragment.mView); if (fragment.mHidden) { 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() { Loading @@ -1197,11 +1200,17 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } }); } } 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) { Loading core/java/android/app/FragmentTransition.java +33 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -308,6 +309,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 Loading Loading
core/java/android/app/Fragment.java +13 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } }
core/java/android/app/FragmentManager.java +20 −11 Original line number Diff line number Diff line Loading @@ -1185,6 +1185,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate if (anim != null) { anim.setTarget(fragment.mView); if (fragment.mHidden) { 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() { Loading @@ -1197,11 +1200,17 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate } }); } } 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) { Loading
core/java/android/app/FragmentTransition.java +33 −0 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -308,6 +309,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 Loading