Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 53ff0bdf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Primary navigation fragments"

parents 1f46283d 5f3a05c1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -4687,6 +4687,7 @@ package android.app {
    method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
    method public abstract int getBackStackEntryCount();
    method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
    method public abstract android.app.Fragment getPrimaryNavigationFragment();
    method public void invalidateOptionsMenu();
    method public abstract boolean isDestroyed();
    method public abstract void popBackStack();
@@ -4763,6 +4764,7 @@ package android.app {
    method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
    method public abstract android.app.FragmentTransaction setTransition(int);
    method public abstract android.app.FragmentTransaction setTransitionStyle(int);
    method public abstract android.app.FragmentTransaction show(android.app.Fragment);
+2 −0
Original line number Diff line number Diff line
@@ -4847,6 +4847,7 @@ package android.app {
    method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
    method public abstract int getBackStackEntryCount();
    method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
    method public abstract android.app.Fragment getPrimaryNavigationFragment();
    method public void invalidateOptionsMenu();
    method public abstract boolean isDestroyed();
    method public abstract void popBackStack();
@@ -4923,6 +4924,7 @@ package android.app {
    method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
    method public abstract android.app.FragmentTransaction setTransition(int);
    method public abstract android.app.FragmentTransaction setTransitionStyle(int);
    method public abstract android.app.FragmentTransaction show(android.app.Fragment);
+2 −0
Original line number Diff line number Diff line
@@ -4697,6 +4697,7 @@ package android.app {
    method public abstract android.app.FragmentManager.BackStackEntry getBackStackEntryAt(int);
    method public abstract int getBackStackEntryCount();
    method public abstract android.app.Fragment getFragment(android.os.Bundle, java.lang.String);
    method public abstract android.app.Fragment getPrimaryNavigationFragment();
    method public void invalidateOptionsMenu();
    method public abstract boolean isDestroyed();
    method public abstract void popBackStack();
@@ -4773,6 +4774,7 @@ package android.app {
    method public abstract android.app.FragmentTransaction setBreadCrumbTitle(java.lang.CharSequence);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int);
    method public abstract android.app.FragmentTransaction setCustomAnimations(int, int, int, int);
    method public abstract android.app.FragmentTransaction setPrimaryNavigationFragment(android.app.Fragment);
    method public abstract android.app.FragmentTransaction setTransition(int);
    method public abstract android.app.FragmentTransaction setTransitionStyle(int);
    method public abstract android.app.FragmentTransaction show(android.app.Fragment);
+104 −45
Original line number Diff line number Diff line
@@ -186,6 +186,8 @@ final class BackStackRecord extends FragmentTransaction implements
    static final int OP_SHOW = 5;
    static final int OP_DETACH = 6;
    static final int OP_ATTACH = 7;
    static final int OP_SET_PRIMARY_NAV = 8;
    static final int OP_UNSET_PRIMARY_NAV = 9;

    static final class Op {
        int cmd;
@@ -194,6 +196,14 @@ final class BackStackRecord extends FragmentTransaction implements
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;

        Op() {
        }

        Op(int cmd, Fragment fragment) {
            this.cmd = cmd;
            this.fragment = fragment;
        }
    }

    ArrayList<Op> mOps = new ArrayList<>();
@@ -318,6 +328,13 @@ final class BackStackRecord extends FragmentTransaction implements
                    case OP_ATTACH:
                        cmdStr = "ATTACH";
                        break;
                    case OP_SET_PRIMARY_NAV:
                        cmdStr="SET_PRIMARY_NAV";
                        break;
                    case OP_UNSET_PRIMARY_NAV:
                        cmdStr="UNSET_PRIMARY_NAV";
                        break;

                    default:
                        cmdStr = "cmd=" + op.cmd;
                        break;
@@ -438,10 +455,7 @@ final class BackStackRecord extends FragmentTransaction implements
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }

        Op op = new Op();
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(opcmd, fragment));
    }

    public FragmentTransaction replace(int containerViewId, Fragment fragment) {
@@ -458,46 +472,37 @@ final class BackStackRecord extends FragmentTransaction implements
    }

    public FragmentTransaction remove(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_REMOVE;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(OP_REMOVE, fragment));

        return this;
    }

    public FragmentTransaction hide(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_HIDE;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(OP_HIDE, fragment));

        return this;
    }

    public FragmentTransaction show(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_SHOW;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(OP_SHOW, fragment));

        return this;
    }

    public FragmentTransaction detach(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_DETACH;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(OP_DETACH, fragment));

        return this;
    }

    public FragmentTransaction attach(Fragment fragment) {
        Op op = new Op();
        op.cmd = OP_ATTACH;
        op.fragment = fragment;
        addOp(op);
        addOp(new Op(OP_ATTACH, fragment));

        return this;
    }

    public FragmentTransaction setPrimaryNavigationFragment(Fragment fragment) {
        addOp(new Op(OP_SET_PRIMARY_NAV, fragment));

        return this;
    }
@@ -689,7 +694,8 @@ final class BackStackRecord extends FragmentTransaction implements
        final int numOps = mOps.size();
        for (int opNum = 0; opNum < numOps; opNum++) {
            final Op op = mOps.get(opNum);
            if (op.fragment.mContainerId == containerId) {
            final int fragContainer = op.fragment != null ? op.fragment.mContainerId : 0;
            if (fragContainer != 0 && fragContainer == containerId) {
                return true;
            }
        }
@@ -704,7 +710,7 @@ final class BackStackRecord extends FragmentTransaction implements
        int lastContainer = -1;
        for (int opNum = 0; opNum < numOps; opNum++) {
            final Op op = mOps.get(opNum);
            final int container = op.fragment.mContainerId;
            final int container = op.fragment != null ? op.fragment.mContainerId : 0;
            if (container != 0 && container != lastContainer) {
                lastContainer = container;
                for (int i = startIndex; i < endIndex; i++) {
@@ -712,7 +718,9 @@ final class BackStackRecord extends FragmentTransaction implements
                    final int numThoseOps = record.mOps.size();
                    for (int thoseOpIndex = 0; thoseOpIndex < numThoseOps; thoseOpIndex++) {
                        final Op thatOp = record.mOps.get(thoseOpIndex);
                        if (thatOp.fragment.mContainerId == container) {
                        final int thatContainer = thatOp.fragment != null
                                ? thatOp.fragment.mContainerId : 0;
                        if (thatContainer == container) {
                            return true;
                        }
                    }
@@ -731,7 +739,9 @@ final class BackStackRecord extends FragmentTransaction implements
        for (int opNum = 0; opNum < numOps; opNum++) {
            final Op op = mOps.get(opNum);
            final Fragment f = op.fragment;
            if (f != null) {
                f.setNextTransition(mTransition, mTransitionStyle);
            }
            switch (op.cmd) {
                case OP_ADD:
                    f.setNextAnim(op.enterAnim);
@@ -757,10 +767,16 @@ final class BackStackRecord extends FragmentTransaction implements
                    f.setNextAnim(op.enterAnim);
                    mManager.attachFragment(f);
                    break;
                case OP_SET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(f);
                    break;
                case OP_UNSET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(null);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            }
            if (!mAllowOptimization && op.cmd != OP_ADD) {
            if (!mAllowOptimization && op.cmd != OP_ADD && f != null) {
                mManager.moveFragmentToExpectedState(f);
            }
        }
@@ -778,7 +794,10 @@ final class BackStackRecord extends FragmentTransaction implements
        for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
            final Op op = mOps.get(opNum);
            Fragment f = op.fragment;
            f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition), mTransitionStyle);
            if (f != null) {
                f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
                        mTransitionStyle);
            }
            switch (op.cmd) {
                case OP_ADD:
                    f.setNextAnim(op.popExitAnim);
@@ -804,10 +823,16 @@ final class BackStackRecord extends FragmentTransaction implements
                    f.setNextAnim(op.popExitAnim);
                    mManager.detachFragment(f);
                    break;
                case OP_SET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(null);
                    break;
                case OP_UNSET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(f);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            }
            if (!mAllowOptimization && op.cmd != OP_REMOVE) {
            if (!mAllowOptimization && op.cmd != OP_REMOVE && f != null) {
                mManager.moveFragmentToExpectedState(f);
            }
        }
@@ -817,15 +842,28 @@ final class BackStackRecord extends FragmentTransaction implements
    }

    /**
     * Removes all OP_REPLACE ops and replaces them with the proper add and remove
     * operations that are equivalent to the replace. This must be called prior to
     * {@link #executeOps()} or any other call that operations on mOps.
     * Expands all meta-ops into their more primitive equivalents. This must be called prior to
     * {@link #executeOps()} or any other call that operations on mOps for forward navigation.
     * It should not be called for pop/reverse navigation operations.
     *
     * <p>Removes all OP_REPLACE ops and replaces them with the proper add and remove
     * operations that are equivalent to the replace.</p>
     *
     * <p>Adds OP_UNSET_PRIMARY_NAV ops to match OP_SET_PRIMARY_NAV, OP_REMOVE and OP_DETACH
     * ops so that we can restore the old primary nav fragment later. Since callers call this
     * method in a loop before running ops from several transactions at once, the caller should
     * pass the return value from this method as the oldPrimaryNav parameter for the next call.
     * The first call in such a loop should pass the value of
     * {@link FragmentManager#getPrimaryNavigationFragment()}.</p>
     *
     * @param added Initialized to the fragments that are in the mManager.mAdded, this
     *              will be modified to contain the fragments that will be in mAdded
     *              after the execution ({@link #executeOps()}.
     * @param oldPrimaryNav The tracked primary navigation fragment as of the beginning of
     *                      this set of ops
     * @return the new oldPrimaryNav fragment after this record's ops would be run
     */
    void expandReplaceOps(ArrayList<Fragment> added) {
    Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
        for (int opNum = 0; opNum < mOps.size(); opNum++) {
            final Op op = mOps.get(opNum);
            switch (op.cmd) {
@@ -834,22 +872,33 @@ final class BackStackRecord extends FragmentTransaction implements
                    added.add(op.fragment);
                    break;
                case OP_REMOVE:
                case OP_DETACH:
                case OP_DETACH: {
                    added.remove(op.fragment);
                    if (op.fragment == oldPrimaryNav) {
                        mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.fragment));
                        opNum++;
                        oldPrimaryNav = null;
                    }
                }
                break;
                case OP_REPLACE: {
                    Fragment f = op.fragment;
                    int containerId = f.mContainerId;
                    final Fragment f = op.fragment;
                    final int containerId = f.mContainerId;
                    boolean alreadyAdded = false;
                    for (int i = added.size() - 1; i >= 0; i--) {
                        Fragment old = added.get(i);
                        final Fragment old = added.get(i);
                        if (old.mContainerId == containerId) {
                            if (old == f) {
                                alreadyAdded = true;
                            } else {
                                Op removeOp = new Op();
                                removeOp.cmd = OP_REMOVE;
                                removeOp.fragment = old;
                                // This is duplicated from above since we only make
                                // a single pass for expanding ops. Unset any outgoing primary nav.
                                if (old == oldPrimaryNav) {
                                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
                                    opNum++;
                                    oldPrimaryNav = null;
                                }
                                final Op removeOp = new Op(OP_REMOVE, old);
                                removeOp.enterAnim = op.enterAnim;
                                removeOp.popEnterAnim = op.popEnterAnim;
                                removeOp.exitAnim = op.exitAnim;
@@ -869,8 +918,18 @@ final class BackStackRecord extends FragmentTransaction implements
                    }
                }
                break;
                case OP_SET_PRIMARY_NAV: {
                    // It's ok if this is null, that means we will restore to no active
                    // primary navigation fragment on a pop.
                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
                    opNum++;
                    // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
                    oldPrimaryNav = op.fragment;
                }
                break;
            }
        }
        return oldPrimaryNav;
    }

    /**
@@ -917,8 +976,8 @@ final class BackStackRecord extends FragmentTransaction implements

    private static boolean isFragmentPostponed(Op op) {
        final Fragment fragment = op.fragment;
        return (fragment.mAdded && fragment.mView != null && !fragment.mDetached &&
                !fragment.mHidden && fragment.isPostponed());
        return fragment != null && fragment.mAdded && fragment.mView != null && !fragment.mDetached
                && !fragment.mHidden && fragment.isPostponed();
    }

    public String getName() {
+62 −5
Original line number Diff line number Diff line
@@ -359,6 +359,18 @@ public abstract class FragmentManager {
     */
    public abstract void unregisterFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb);

    /**
     * Return the currently active primary navigation fragment for this FragmentManager.
     *
     * <p>The primary navigation fragment's
     * {@link Fragment#getChildFragmentManager() child FragmentManager} will be called first
     * to process delegated navigation actions such as {@link #popBackStack()} if no ID
     * or transaction name is provided to pop to.</p>
     *
     * @return the fragment designated as the primary navigation fragment
     */
    public abstract Fragment getPrimaryNavigationFragment();

    /**
     * Print the FragmentManager's state into the given stream.
     *
@@ -524,6 +536,7 @@ final class FragmentManagerState implements Parcelable {
    FragmentState[] mActive;
    int[] mAdded;
    BackStackState[] mBackStack;
    int mPrimaryNavActiveIndex = -1;
    
    public FragmentManagerState() {
    }
@@ -532,6 +545,7 @@ final class FragmentManagerState implements Parcelable {
        mActive = in.createTypedArray(FragmentState.CREATOR);
        mAdded = in.createIntArray();
        mBackStack = in.createTypedArray(BackStackState.CREATOR);
        mPrimaryNavActiveIndex = in.readInt();
    }
    
    public int describeContents() {
@@ -542,6 +556,7 @@ final class FragmentManagerState implements Parcelable {
        dest.writeTypedArray(mActive, flags);
        dest.writeIntArray(mAdded);
        dest.writeTypedArray(mBackStack, flags);
        dest.writeInt(mPrimaryNavActiveIndex);
    }
    
    public static final Parcelable.Creator<FragmentManagerState> CREATOR
@@ -626,6 +641,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
    FragmentHostCallback<?> mHost;
    FragmentContainer mContainer;
    Fragment mParent;
    Fragment mPrimaryNav;
    
    boolean mNeedMenuInvalidate;
    boolean mStateSaved;
@@ -783,6 +799,16 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        execPendingActions();
        ensureExecReady(true);

        if (mPrimaryNav != null // We have a primary nav fragment
                && id < 0 // No valid id (since they're local)
                && name == null) { // no name to pop to (since they're local)
            final FragmentManager childManager = mPrimaryNav.mChildFragmentManager;
            if (childManager != null && childManager.popBackStackImmediate()) {
                // We did something, just not to this specific FragmentManager. Return true.
                return true;
            }
        }

        boolean executePop = popBackStackState(mTmpRecords, mTmpIsPop, name, id, flags);
        if (executePop) {
            mExecutingActions = true;
@@ -2038,11 +2064,12 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        if (mAdded != null) {
            mTmpAddedFragments.addAll(mAdded);
        }
        Fragment oldPrimaryNav = getPrimaryNavigationFragment();
        for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
            final BackStackRecord record = records.get(recordNum);
            final boolean isPop = isRecordPop.get(recordNum);
            if (!isPop) {
                record.expandReplaceOps(mTmpAddedFragments);
                oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
            } else {
                record.trackAddedFragmentsInPop(mTmpAddedFragments);
            }
@@ -2318,20 +2345,20 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
     */
    private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
            ArrayList<Boolean> isPop) {
        int numActions;
        boolean didSomething = false;
        synchronized (this) {
            if (mPendingActions == null || mPendingActions.size() == 0) {
                return false;
            }

            numActions = mPendingActions.size();
            final int numActions = mPendingActions.size();
            for (int i = 0; i < numActions; i++) {
                mPendingActions.get(i).generateOps(records, isPop);
                didSomething |= mPendingActions.get(i).generateOps(records, isPop);
            }
            mPendingActions.clear();
            mHost.getHandler().removeCallbacks(mExecCommit);
        }
        return numActions > 0;
        return didSomething;
    }

    void doPendingDeferredStart() {
@@ -2618,6 +2645,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        fms.mActive = active;
        fms.mAdded = added;
        fms.mBackStack = backStack;
        if (mPrimaryNav != null) {
            fms.mPrimaryNavActiveIndex = mPrimaryNav.mIndex;
        }
        return fms;
    }
    
@@ -2744,6 +2774,10 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        } else {
            mBackStack = null;
        }

        if (fms.mPrimaryNavActiveIndex >= 0) {
            mPrimaryNav = mActive.get(fms.mPrimaryNavActiveIndex);
        }
    }
    
    public void attachController(FragmentHostCallback<?> host, FragmentContainer container,
@@ -2942,6 +2976,19 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        }
    }

    public void setPrimaryNavigationFragment(Fragment f) {
        if (f != null && (f.getFragmentManager() != this || f.mIndex >= mActive.size()
                || mActive.get(f.mIndex) != f)) {
            throw new IllegalArgumentException("Fragment " + f
                    + " is not an active fragment of FragmentManager " + this);
        }
        mPrimaryNav = f;
    }

    public Fragment getPrimaryNavigationFragment() {
        return mPrimaryNav;
    }

    public void registerFragmentLifecycleCallbacks(FragmentLifecycleCallbacks cb,
            boolean recursive) {
        if (mLifecycleCallbacks == null) {
@@ -3386,6 +3433,16 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
        @Override
        public boolean generateOps(ArrayList<BackStackRecord> records,
                ArrayList<Boolean> isRecordPop) {
            if (mPrimaryNav != null // We have a primary nav fragment
                    && mId < 0 // No valid id (since they're local)
                    && mName == null) { // no name to pop to (since they're local)
                final FragmentManager childManager = mPrimaryNav.mChildFragmentManager;
                if (childManager != null && childManager.popBackStackImmediate()) {
                    // We didn't add any operations for this FragmentManager even though
                    // a child did do work.
                    return false;
                }
            }
            return popBackStackState(records, isRecordPop, mName, mId, mFlags);
        }
    }
Loading