diff options
| -rw-r--r-- | core/java/android/app/BackStackRecord.java | 193 | ||||
| -rw-r--r-- | core/java/android/app/FragmentManager.java | 17 |
2 files changed, 106 insertions, 104 deletions
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java index f4f8d6936247..a4b1a1f50104 100644 --- a/core/java/android/app/BackStackRecord.java +++ b/core/java/android/app/BackStackRecord.java @@ -669,10 +669,9 @@ final class BackStackRecord extends FragmentTransaction implements bumpBackStackNesting(1); if (mManager.mCurState >= Fragment.CREATED) { - SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); - SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); - calculateFragments(firstOutFragments, lastInFragments); - beginTransition(firstOutFragments, lastInFragments, false); + SparseArray<FragmentContainerTransition> transitioningFragments = new SparseArray<>(); + calculateFragments(transitioningFragments); + beginTransition(transitioningFragments); } final int numOps = mOps.size(); @@ -783,32 +782,44 @@ final class BackStackRecord extends FragmentTransaction implements } } - private static void setFirstOut(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments, Fragment fragment) { + private static void setFirstOut(SparseArray<FragmentContainerTransition> transitioningFragments, + Fragment fragment, boolean isPop) { if (fragment != null) { int containerId = fragment.mContainerId; if (containerId != 0 && !fragment.isHidden()) { - if (fragment.isAdded() && fragment.getView() != null - && firstOutFragments.get(containerId) == null) { - firstOutFragments.put(containerId, fragment); + FragmentContainerTransition fragments = transitioningFragments.get(containerId); + if (fragment.isAdded() && fragment.getView() != null && (fragments == null || + fragments.firstOut == null)) { + if (fragments == null) { + fragments = new FragmentContainerTransition(); + transitioningFragments.put(containerId, fragments); + } + fragments.firstOut = fragment; + fragments.firstOutIsPop = isPop; } - if (lastInFragments.get(containerId) == fragment) { - lastInFragments.remove(containerId); + if (fragments != null && fragments.lastIn == fragment) { + fragments.lastIn = null; } } } } - private void setLastIn(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments, Fragment fragment) { + private void setLastIn(SparseArray<FragmentContainerTransition> transitioningFragments, + Fragment fragment, boolean isPop) { if (fragment != null) { int containerId = fragment.mContainerId; if (containerId != 0) { + FragmentContainerTransition fragments = transitioningFragments.get(containerId); if (!fragment.isAdded()) { - lastInFragments.put(containerId, fragment); + if (fragments == null) { + fragments = new FragmentContainerTransition(); + transitioningFragments.put(containerId, fragments); + } + fragments.lastIn = fragment; + fragments.lastInIsPop = isPop; } - if (firstOutFragments.get(containerId) == fragment) { - firstOutFragments.remove(containerId); + if (fragments != null && fragments.firstOut == fragment) { + fragments.firstOut = null; } } /** @@ -828,13 +839,12 @@ final class BackStackRecord extends FragmentTransaction implements * Finds the first removed fragment and last added fragments when going forward. * If none of the fragments have transitions, then both lists will be empty. * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. This list will be modified by the method. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. This list will be modified by the method. + * @param transitioningFragments Keyed on the container ID, the first fragments to be removed, + * and last fragments to be added. This will be modified by + * this method. */ - private void calculateFragments(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments) { + private void calculateFragments( + SparseArray<FragmentContainerTransition> transitioningFragments) { if (!mManager.mContainer.onHasView()) { return; // nothing to see, so no transitions } @@ -843,22 +853,14 @@ final class BackStackRecord extends FragmentTransaction implements final Op op = mOps.get(opNum); switch (op.cmd) { case OP_ADD: - setLastIn(firstOutFragments, lastInFragments, op.fragment); + case OP_SHOW: + case OP_ATTACH: + setLastIn(transitioningFragments, op.fragment, false); break; case OP_REMOVE: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; case OP_HIDE: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_SHOW: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; case OP_DETACH: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_ATTACH: - setLastIn(firstOutFragments, lastInFragments, op.fragment); + setFirstOut(transitioningFragments, op.fragment, false); break; } } @@ -868,13 +870,12 @@ final class BackStackRecord extends FragmentTransaction implements * Finds the first removed fragment and last added fragments when popping the back stack. * If none of the fragments have transitions, then both lists will be empty. * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. This list will be modified by the method. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. This list will be modified by the method. + * @param transitioningFragments Keyed on the container ID, the first fragments to be removed, + * and last fragments to be added. This will be modified by + * this method. */ - public void calculateBackFragments(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments) { + public void calculateBackFragments( + SparseArray<FragmentContainerTransition> transitioningFragments) { if (!mManager.mContainer.onHasView()) { return; // nothing to see, so no transitions } @@ -883,22 +884,14 @@ final class BackStackRecord extends FragmentTransaction implements final Op op = mOps.get(opNum); switch (op.cmd) { case OP_ADD: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); + case OP_SHOW: + case OP_ATTACH: + setFirstOut(transitioningFragments, op.fragment, true); break; case OP_REMOVE: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; case OP_HIDE: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_SHOW: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); - break; case OP_DETACH: - setLastIn(firstOutFragments, lastInFragments, op.fragment); - break; - case OP_ATTACH: - setFirstOut(firstOutFragments, lastInFragments, op.fragment); + setLastIn(transitioningFragments, op.fragment, true); break; } } @@ -925,18 +918,12 @@ final class BackStackRecord extends FragmentTransaction implements * outgoing fragment's return shared element transition is used. Shared element * transitions only operate if there is both an incoming and outgoing fragment.</p> * - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. - * @param isBack true if this is popping the back stack or false if this is a - * forward operation. + * @param containers The first in and last out fragments that are transitioning. * @return The TransitionState used to complete the operation of the transition * in {@link #setNameOverrides(android.app.BackStackRecord.TransitionState, java.util.ArrayList, * java.util.ArrayList)}. */ - private TransitionState beginTransition(SparseArray<Fragment> firstOutFragments, - SparseArray<Fragment> lastInFragments, boolean isBack) { + private TransitionState beginTransition(SparseArray<FragmentContainerTransition> containers) { TransitionState state = new TransitionState(); // Adding a non-existent target view makes sure that the transitions don't target @@ -944,20 +931,11 @@ final class BackStackRecord extends FragmentTransaction implements // add any, then no views will be targeted. state.nonExistentView = new View(mManager.mHost.getContext()); - // Go over all leaving fragments. - for (int i = 0; i < firstOutFragments.size(); i++) { - int containerId = firstOutFragments.keyAt(i); - configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments); - } - - // Now go over all entering fragments that didn't have a leaving fragment. - for (int i = 0; i < lastInFragments.size(); i++) { - int containerId = lastInFragments.keyAt(i); - if (firstOutFragments.get(containerId) == null) { - configureTransitions(containerId, state, isBack, firstOutFragments, - lastInFragments); - } + final int numContainers = containers.size(); + for (int i = 0; i < numContainers; i++) { + int containerId = containers.keyAt(i); + FragmentContainerTransition containerTransition = containers.valueAt(i); + configureTransitions(containerId, state, containerTransition); } return state; } @@ -1225,24 +1203,21 @@ final class BackStackRecord extends FragmentTransaction implements * * @param containerId The container ID of the fragments to configure the transition for. * @param state The Transition State keeping track of the executing transitions. - * @param firstOutFragments The list of first fragments to be removed, keyed on the - * container ID. - * @param lastInFragments The list of last fragments to be added, keyed on the - * container ID. - * @param isBack true if this is popping the back stack or false if this is a - * forward operation. + * @param transitioningFragments The first out and last in fragments for the fragment container. */ - private void configureTransitions(int containerId, TransitionState state, boolean isBack, - SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { + private void configureTransitions(int containerId, TransitionState state, + FragmentContainerTransition transitioningFragments) { ViewGroup sceneRoot = (ViewGroup) mManager.mContainer.onFindViewById(containerId); if (sceneRoot != null) { - Fragment inFragment = lastInFragments.get(containerId); - Fragment outFragment = firstOutFragments.get(containerId); + final Fragment inFragment = transitioningFragments.lastIn; + final Fragment outFragment = transitioningFragments.firstOut; - Transition enterTransition = getEnterTransition(inFragment, isBack); - TransitionSet sharedElementTransition = - getSharedElementTransition(inFragment, outFragment, isBack); - Transition exitTransition = getExitTransition(outFragment, isBack); + Transition enterTransition = + getEnterTransition(inFragment, transitioningFragments.lastInIsPop); + TransitionSet sharedElementTransition = getSharedElementTransition(inFragment, + outFragment, transitioningFragments.lastInIsPop); + Transition exitTransition = + getExitTransition(outFragment, transitioningFragments.firstOutIsPop); if (enterTransition == null && sharedElementTransition == null && exitTransition == null) { @@ -1254,12 +1229,13 @@ final class BackStackRecord extends FragmentTransaction implements ArrayMap<String, View> namedViews = null; ArrayList<View> sharedElementTargets = new ArrayList<View>(); if (sharedElementTransition != null) { - namedViews = remapSharedElements(state, outFragment, isBack); + namedViews = remapSharedElements(state, outFragment, + transitioningFragments.firstOutIsPop); setSharedElementTargets(sharedElementTransition, state.nonExistentView, namedViews, sharedElementTargets); // Notify the start of the transition. - SharedElementCallback callback = isBack ? + SharedElementCallback callback = transitioningFragments.lastInIsPop ? outFragment.mEnterTransitionCallback : inFragment.mEnterTransitionCallback; ArrayList<String> names = new ArrayList<String>(namedViews.keySet()); @@ -1290,13 +1266,14 @@ final class BackStackRecord extends FragmentTransaction implements } Transition transition = mergeTransitions(enterTransition, exitTransition, - sharedElementTransition, inFragment, isBack); + sharedElementTransition, inFragment, transitioningFragments.lastInIsPop); if (transition != null) { ArrayList<View> hiddenFragments = new ArrayList<View>(); ArrayList<View> enteringViews = addTransitionTargets(state, enterTransition, sharedElementTransition, exitTransition, transition, sceneRoot, inFragment, - outFragment, hiddenFragments, isBack, sharedElementTargets); + outFragment, hiddenFragments, transitioningFragments.lastInIsPop, + sharedElementTargets); transition.setNameOverrides(state.nameOverrides); // We want to exclude hidden views later, so we need a non-null list in the @@ -1589,7 +1566,7 @@ final class BackStackRecord extends FragmentTransaction implements } public TransitionState popFromBackStack(boolean doStateMove, TransitionState state, - SparseArray<Fragment> firstOutFragments, SparseArray<Fragment> lastInFragments) { + SparseArray<FragmentContainerTransition> transitioningFragments) { if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "popFromBackStack: " + this); LogWriter logw = new LogWriter(Log.VERBOSE, TAG); @@ -1600,8 +1577,8 @@ final class BackStackRecord extends FragmentTransaction implements if (mManager.mCurState >= Fragment.CREATED) { if (state == null) { - if (firstOutFragments.size() != 0 || lastInFragments.size() != 0) { - state = beginTransition(firstOutFragments, lastInFragments, true); + if (transitioningFragments.size() != 0) { + state = beginTransition(transitioningFragments); } } else if (!doStateMove) { setNameOverrides(state, mSharedElementTargetNames, mSharedElementSourceNames); @@ -1742,4 +1719,30 @@ final class BackStackRecord extends FragmentTransaction implements public View enteringEpicenterView; public View nonExistentView; } + + /** + * Tracks the last fragment added and first fragment removed for fragment transitions. + * This also tracks which fragments are changed by push or pop transactions. + */ + public static class FragmentContainerTransition { + /** + * The last fragment added/attached/shown in its container + */ + public Fragment lastIn; + + /** + * true when lastIn was added during a pop transaction or false if added with a push + */ + public boolean lastInIsPop; + + /** + * The first fragment with a View that was removed/detached/hidden in its container. + */ + public Fragment firstOut; + + /** + * true when firstOut was removed during a pop transaction or false otherwise + */ + public boolean firstOutIsPop; + } } diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 7394c7fcf975..099bae479bc4 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -1635,12 +1635,12 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate return false; } final BackStackRecord bss = mBackStack.remove(last); - SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); - SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + SparseArray<BackStackRecord.FragmentContainerTransition> transitioningFragments = + new SparseArray<>(); if (mCurState >= Fragment.CREATED) { - bss.calculateBackFragments(firstOutFragments, lastInFragments); + bss.calculateBackFragments(transitioningFragments); } - bss.popFromBackStack(true, null, firstOutFragments, lastInFragments); + bss.popFromBackStack(true, null, transitioningFragments); reportBackStackChanged(); } else { int index = -1; @@ -1684,18 +1684,17 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate states.add(mBackStack.remove(i)); } final int LAST = states.size()-1; - SparseArray<Fragment> firstOutFragments = new SparseArray<Fragment>(); - SparseArray<Fragment> lastInFragments = new SparseArray<Fragment>(); + SparseArray<BackStackRecord.FragmentContainerTransition> transitioningFragments = + new SparseArray<>(); if (mCurState >= Fragment.CREATED) { for (int i = 0; i <= LAST; i++) { - states.get(i).calculateBackFragments(firstOutFragments, lastInFragments); + states.get(i).calculateBackFragments(transitioningFragments); } } BackStackRecord.TransitionState state = null; for (int i=0; i<=LAST; i++) { if (DEBUG) Log.v(TAG, "Popping back stack state: " + states.get(i)); - state = states.get(i).popFromBackStack(i == LAST, state, - firstOutFragments, lastInFragments); + state = states.get(i).popFromBackStack(i == LAST, state, transitioningFragments); } reportBackStackChanged(); } |