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

Commit 1c11015e authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android (Google) Code Review
Browse files

Merge "Add Fragment option menu APIs."

parents ed3939fe b31e84bc
Loading
Loading
Loading
Loading
+98 −7
Original line number Diff line number Diff line
@@ -20306,6 +20306,17 @@
 visibility="public"
>
</method>
<method name="invalidateOptionsMenu"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="isChangingConfigurations"
 return="boolean"
 abstract="false"
@@ -25543,7 +25554,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25554,7 +25565,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25565,7 +25576,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25576,7 +25587,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25609,7 +25620,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25620,7 +25631,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25631,7 +25642,7 @@
 native="false"
 synchronized="false"
 static="false"
 final="false"
 final="true"
 deprecated="not deprecated"
 visibility="public"
>
@@ -25709,6 +25720,21 @@
<parameter name="nextAnim" type="int">
</parameter>
</method>
<method name="onCreateOptionsMenu"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="menu" type="android.view.Menu">
</parameter>
<parameter name="inflater" type="android.view.MenuInflater">
</parameter>
</method>
<method name="onCreateView"
 return="android.view.View"
 abstract="false"
@@ -25789,6 +25815,32 @@
 visibility="public"
>
</method>
<method name="onOptionsItemSelected"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="item" type="android.view.MenuItem">
</parameter>
</method>
<method name="onOptionsMenuClosed"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="menu" type="android.view.Menu">
</parameter>
</method>
<method name="onPause"
 return="void"
 abstract="false"
@@ -25800,6 +25852,19 @@
 visibility="public"
>
</method>
<method name="onPrepareOptionsMenu"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="menu" type="android.view.Menu">
</parameter>
</method>
<method name="onReady"
 return="void"
 abstract="false"
@@ -25859,6 +25924,19 @@
 visibility="public"
>
</method>
<method name="setHasOptionsMenu"
 return="void"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="hasMenu" type="boolean">
</parameter>
</method>
<method name="setRetainInstance"
 return="void"
 abstract="false"
@@ -189432,6 +189510,19 @@
 visibility="protected"
>
</method>
<method name="invalidatePanelMenu"
 return="void"
 abstract="true"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
<parameter name="featureId" type="int">
</parameter>
</method>
<method name="isActive"
 return="boolean"
 abstract="false"
+19 −5
Original line number Diff line number Diff line
@@ -77,9 +77,6 @@ import android.widget.LinearLayout;
import com.android.internal.app.SplitActionBar;
import com.android.internal.policy.PolicyManager;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * An activity is a single, focused thing that the user can do.  Almost all
 * activities interact with the user, so the Activity class takes care of
@@ -2242,7 +2239,9 @@ public class Activity extends ContextThemeWrapper
     */
    public boolean onCreatePanelMenu(int featureId, Menu menu) {
        if (featureId == Window.FEATURE_OPTIONS_PANEL) {
            return onCreateOptionsMenu(menu);
            boolean show = onCreateOptionsMenu(menu);
            show |= mFragments.dispatchCreateOptionsMenu(menu, getMenuInflater());
            return show;
        }
        return false;
    }
@@ -2259,6 +2258,7 @@ public class Activity extends ContextThemeWrapper
    public boolean onPreparePanel(int featureId, View view, Menu menu) {
        if (featureId == Window.FEATURE_OPTIONS_PANEL && menu != null) {
            boolean goforit = onPrepareOptionsMenu(menu);
            goforit |= mFragments.dispatchPrepareOptionsMenu(menu);
            return goforit && menu.hasVisibleItems();
        }
        return true;
@@ -2289,7 +2289,10 @@ public class Activity extends ContextThemeWrapper
                // doesn't call through to superclass's implmeentation of each
                // of these methods below
                EventLog.writeEvent(50000, 0, item.getTitleCondensed());
                return onOptionsItemSelected(item);
                if (onOptionsItemSelected(item)) {
                    return true;
                }
                return mFragments.dispatchOptionsItemSelected(item);
                
            case Window.FEATURE_CONTEXT_MENU:
                EventLog.writeEvent(50000, 1, item.getTitleCondensed());
@@ -2312,6 +2315,7 @@ public class Activity extends ContextThemeWrapper
    public void onPanelClosed(int featureId, Menu menu) {
        switch (featureId) {
            case Window.FEATURE_OPTIONS_PANEL:
                mFragments.dispatchOptionsMenuClosed(menu);
                onOptionsMenuClosed(menu);
                break;
                
@@ -2321,6 +2325,15 @@ public class Activity extends ContextThemeWrapper
        }
    }

    /**
     * Declare that the options menu has changed, so should be recreated.
     * The {@link #onCreateOptionsMenu(Menu)} method will be called the next
     * time it needs to be displayed.
     */
    public void invalidateOptionsMenu() {
        mWindow.invalidatePanelMenu(Window.FEATURE_OPTIONS_PANEL);
    }
    
    /**
     * Initialize the contents of the Activity's standard options menu.  You
     * should place your menu items in to <var>menu</var>.
@@ -3887,6 +3900,7 @@ public class Activity extends ContextThemeWrapper
                fragment.mFromLayout = true;
                fragment.mFragmentId = id;
                fragment.mTag = tag;
                fragment.mImmediateActivity = this;
                mFragments.addFragment(fragment, true);
            }
            // If this fragment is newly instantiated (either right now, or
+75 −21
Original line number Diff line number Diff line
@@ -100,9 +100,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
    
    static final int OP_NULL = 0;
    static final int OP_ADD = 1;
    static final int OP_REMOVE = 2;
    static final int OP_HIDE = 3;
    static final int OP_SHOW = 4;
    static final int OP_REPLACE = 2;
    static final int OP_REMOVE = 3;
    static final int OP_HIDE = 4;
    static final int OP_SHOW = 5;
    
    static final class Op {
        Op next;
@@ -111,6 +112,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        ArrayList<Fragment> removed;
    }
    
    Op mHead;
@@ -142,17 +144,25 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
    }
        
    public FragmentTransaction add(Fragment fragment, String tag) {
        return add(0, fragment, tag);
        doAddOp(0, fragment, tag, OP_ADD);
        return this;
    }

    public FragmentTransaction add(int containerViewId, Fragment fragment) {
        return add(containerViewId, fragment, null);
        doAddOp(containerViewId, fragment, null, OP_ADD);
        return this;
    }

    public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
        if (fragment.mActivity != null) {
        doAddOp(containerViewId, fragment, tag, OP_ADD);
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
        if (fragment.mImmediateActivity != null) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }
        fragment.mImmediateActivity = mManager.mActivity;
        
        if (tag != null) {
            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
@@ -173,11 +183,9 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
        }
        
        Op op = new Op();
        op.cmd = OP_ADD;
        op.cmd = opcmd;
        op.fragment = fragment;
        addOp(op);
        
        return this;
    }

    public FragmentTransaction replace(int containerViewId, Fragment fragment) {
@@ -188,21 +196,16 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        }
        if (mManager.mAdded != null) {
            for (int i=0; i<mManager.mAdded.size(); i++) {
                Fragment old = mManager.mAdded.get(i);
                if (old.mContainerId == containerViewId) {
                    remove(old);
                }
            }
        }
        return add(containerViewId, fragment, tag);
        
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }
    
    public FragmentTransaction remove(Fragment fragment) {
        if (fragment.mActivity == null) {
        if (fragment.mImmediateActivity == null) {
            throw new IllegalStateException("Fragment not added: " + fragment);
        }
        fragment.mImmediateActivity = null;
        
        Op op = new Op();
        op.cmd = OP_REMOVE;
@@ -213,7 +216,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
    }

    public FragmentTransaction hide(Fragment fragment) {
        if (fragment.mActivity == null) {
        if (fragment.mImmediateActivity == null) {
            throw new IllegalStateException("Fragment not added: " + fragment);
        }
        
@@ -226,7 +229,7 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
    }
    
    public FragmentTransaction show(Fragment fragment) {
        if (fragment.mActivity == null) {
        if (fragment.mImmediateActivity == null) {
            throw new IllegalStateException("Fragment not added: " + fragment);
        }
        
@@ -278,6 +281,30 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
                    f.mNextAnim = op.enterAnim;
                    mManager.addFragment(f, false);
                } break;
                case OP_REPLACE: {
                    Fragment f = op.fragment;
                    if (mManager.mAdded != null) {
                        for (int i=0; i<mManager.mAdded.size(); i++) {
                            Fragment old = mManager.mAdded.get(i);
                            if (old.mContainerId == f.mContainerId) {
                                if (op.removed == null) {
                                    op.removed = new ArrayList<Fragment>();
                                }
                                op.removed.add(old);
                                if (mAddToBackStack) {
                                    old.mBackStackNesting++;
                                }
                                old.mNextAnim = op.exitAnim;
                                mManager.removeFragment(old, mTransition, mTransitionStyle);
                            }
                        }
                    }
                    if (mAddToBackStack) {
                        f.mBackStackNesting++;
                    }
                    f.mNextAnim = op.enterAnim;
                    mManager.addFragment(f, false);
                } break;
                case OP_REMOVE: {
                    Fragment f = op.fragment;
                    if (mAddToBackStack) {
@@ -312,6 +339,11 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
        
        mManager.moveToState(mManager.mCurState, mTransition,
                mTransitionStyle, true);
        if (mManager.mNeedMenuInvalidate && mManager.mActivity != null) {
            mManager.mActivity.invalidateOptionsMenu();
            mManager.mNeedMenuInvalidate = false;
        }
        
        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
@@ -330,6 +362,24 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
                            FragmentManager.reverseTransit(mTransition),
                            mTransitionStyle);
                } break;
                case OP_REPLACE: {
                    Fragment f = op.fragment;
                    if (mAddToBackStack) {
                        f.mBackStackNesting--;
                    }
                    mManager.removeFragment(f,
                            FragmentManager.reverseTransit(mTransition),
                            mTransitionStyle);
                    if (op.removed != null) {
                        for (int i=0; i<op.removed.size(); i++) {
                            Fragment old = op.removed.get(i);
                            if (mAddToBackStack) {
                                old.mBackStackNesting--;
                            }
                            mManager.addFragment(old, false);
                        }
                    }
                } break;
                case OP_REMOVE: {
                    Fragment f = op.fragment;
                    if (mAddToBackStack) {
@@ -363,6 +413,10 @@ final class BackStackEntry implements FragmentTransaction, Runnable {
        
        mManager.moveToState(mManager.mCurState,
                FragmentManager.reverseTransit(mTransition), mTransitionStyle, true);
        if (mManager.mNeedMenuInvalidate && mManager.mActivity != null) {
            mManager.mActivity.invalidateOptionsMenu();
            mManager.mNeedMenuInvalidate = false;
        }
    }
    
    public String getName() {
+98 −7
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
@@ -157,6 +160,10 @@ public class Fragment implements ComponentCallbacks {
    // Number of active back stack entries this fragment is in.
    int mBackStackNesting;
    
    // Set as soon as a fragment is added to a transaction (or removed),
    // to be able to do validation.
    Activity mImmediateActivity;
    
    // Activity this fragment is attached to.
    Activity mActivity;
    
@@ -184,6 +191,9 @@ public class Fragment implements ComponentCallbacks {
    // If set this fragment is being retained across the current config change.
    boolean mRetaining;
    
    // If set this fragment has menu items to contribute.
    boolean mHasMenu;
    
    // Used to verify that subclasses call through to super class.
    boolean mCalled;
    
@@ -270,28 +280,28 @@ public class Fragment implements ComponentCallbacks {
     * the android:id value supplied in a layout or the container view ID
     * supplied when adding the fragment.
     */
    public int getId() {
    final public int getId() {
        return mFragmentId;
    }
    
    /**
     * Get the tag name of the fragment, if specified.
     */
    public String getTag() {
    final public String getTag() {
        return mTag;
    }
    
    /**
     * Return the Activity this fragment is currently associated with.
     */
    public Activity getActivity() {
    final public Activity getActivity() {
        return mActivity;
    }
    
    /**
     * Return true if the fragment is currently added to its activity.
     */
    public boolean isAdded() {
    final public boolean isAdded() {
        return mActivity != null && mActivity.mFragments.mAdded.contains(this);
    }
    
@@ -300,7 +310,7 @@ public class Fragment implements ComponentCallbacks {
     * it: (1) has been added, (2) has its view attached to the window, and 
     * (3) is not hidden.
     */
    public boolean isVisible() {
    final public boolean isVisible() {
        return isAdded() && !isHidden() && mView != null
                && mView.getWindowToken() != null && mView.getVisibility() == View.VISIBLE;
    }
@@ -312,7 +322,7 @@ public class Fragment implements ComponentCallbacks {
     * to other states -- that is, to be visible to the user, a fragment
     * must be both started and not hidden.
     */
    public boolean isHidden() {
    final public boolean isHidden() {
        return mHidden;
    }
    
@@ -344,10 +354,26 @@ public class Fragment implements ComponentCallbacks {
        mRetainInstance = retain;
    }
    
    public boolean getRetainInstance() {
    final public boolean getRetainInstance() {
        return mRetainInstance;
    }
    
    /**
     * Report that this fragment would like to participate in populating
     * the options menu by receiving a call to {@link #onCreateOptionsMenu(Menu)}
     * and related methods.
     * 
     * @param hasMenu If true, the fragment has menu items to contribute.
     */
    public void setHasOptionsMenu(boolean hasMenu) {
        if (mHasMenu != hasMenu) {
            mHasMenu = hasMenu;
            if (isAdded() && !isHidden()) {
                mActivity.invalidateOptionsMenu();
            }
        }
    }
    
    /**
     * Call {@link Activity#startActivity(Intent)} on the fragment's
     * containing Activity.
@@ -526,4 +552,69 @@ public class Fragment implements ComponentCallbacks {
    public void onDetach() {
        mCalled = true;
    }
    
    /**
     * Initialize the contents of the Activity's standard options menu.  You
     * should place your menu items in to <var>menu</var>.  For this method
     * to be called, you must have first called {@link #setHasMenu}.  See
     * {@link Activity#onCreateOptionsMenu(Menu) Activity.onCreateOptionsMenu}
     * for more information.
     * 
     * @param menu The options menu in which you place your items.
     * 
     * @see #setHasMenu
     * @see #onPrepareOptionsMenu
     * @see #onOptionsItemSelected
     */
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    }

    /**
     * Prepare the Screen's standard options menu to be displayed.  This is
     * called right before the menu is shown, every time it is shown.  You can
     * use this method to efficiently enable/disable items or otherwise
     * dynamically modify the contents.  See
     * {@link Activity#onPrepareOptionsMenu(Menu) Activity.onPrepareOptionsMenu}
     * for more information.
     * 
     * @param menu The options menu as last shown or first initialized by
     *             onCreateOptionsMenu().
     * 
     * @see #setHasMenu
     * @see #onCreateOptionsMenu
     */
    public void onPrepareOptionsMenu(Menu menu) {
    }

    /**
     * This hook is called whenever an item in your options menu is selected.
     * The default implementation simply returns false to have the normal
     * processing happen (calling the item's Runnable or sending a message to
     * its Handler as appropriate).  You can use this method for any items
     * for which you would like to do processing without those other
     * facilities.
     * 
     * <p>Derived classes should call through to the base class for it to
     * perform the default menu handling.
     * 
     * @param item The menu item that was selected.
     * 
     * @return boolean Return false to allow normal menu processing to
     *         proceed, true to consume it here.
     * 
     * @see #onCreateOptionsMenu
     */
    public boolean onOptionsItemSelected(MenuItem item) {
        return false;
    }

    /**
     * This hook is called whenever the options menu is being closed (either by the user canceling
     * the menu with the back/menu button, or when an item is selected).
     *  
     * @param menu The options menu as last shown or first initialized by
     *             onCreateOptionsMenu().
     */
    public void onOptionsMenuClosed(Menu menu) {
    }
}
+71 −0
Original line number Diff line number Diff line
@@ -23,6 +23,9 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
@@ -82,6 +85,8 @@ public class FragmentManager {
    int mCurState = Fragment.INITIALIZING;
    Activity mActivity;
    
    boolean mNeedMenuInvalidate;
    
    // Temporary vars for state save and restore.
    Bundle mStateBundle = null;
    SparseArray<Parcelable> mStateArray = null;
@@ -362,6 +367,9 @@ public class FragmentManager {
        mAdded.add(fragment);
        makeActive(fragment);
        fragment.mAdded = true;
        if (fragment.mHasMenu) {
            mNeedMenuInvalidate = true;
        }
        if (moveToStateNow) {
            moveToState(fragment, mCurState, 0, 0);
        }
@@ -374,6 +382,9 @@ public class FragmentManager {
        if (inactive) {
            makeInactive(fragment);
        }
        if (fragment.mHasMenu) {
            mNeedMenuInvalidate = true;
        }
        fragment.mAdded = false;
        moveToState(fragment, inactive ? Fragment.INITIALIZING : Fragment.CREATED,
                transition, transitionStyle);
@@ -391,6 +402,9 @@ public class FragmentManager {
                }
                fragment.mView.setVisibility(View.GONE);
            }
            if (fragment.mAdded && fragment.mHasMenu) {
                mNeedMenuInvalidate = true;
            }
            fragment.onHiddenChanged(true);
        }
    }
@@ -407,6 +421,9 @@ public class FragmentManager {
                }
                fragment.mView.setVisibility(View.VISIBLE);
            }
            if (fragment.mAdded && fragment.mHasMenu) {
                mNeedMenuInvalidate = true;
            }
            fragment.onHiddenChanged(false);
        }
    }
@@ -673,6 +690,7 @@ public class FragmentManager {
                            "No instantiated fragment for index #" + fms.mAdded[i]);
                }
                f.mAdded = true;
                f.mImmediateActivity = mActivity;
                mAdded.add(f);
            }
        } else {
@@ -721,6 +739,59 @@ public class FragmentManager {
        mActivity = null;
    }
    
    public boolean dispatchCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        boolean show = false;
        if (mActive != null) {
            for (int i=0; i<mAdded.size(); i++) {
                Fragment f = mAdded.get(i);
                if (f != null && !f.mHidden && f.mHasMenu) {
                    show = true;
                    f.onCreateOptionsMenu(menu, inflater);
                }
            }
        }
        return show;
    }
    
    public boolean dispatchPrepareOptionsMenu(Menu menu) {
        boolean show = false;
        if (mActive != null) {
            for (int i=0; i<mAdded.size(); i++) {
                Fragment f = mAdded.get(i);
                if (f != null && !f.mHidden && f.mHasMenu) {
                    show = true;
                    f.onPrepareOptionsMenu(menu);
                }
            }
        }
        return show;
    }
    
    public boolean dispatchOptionsItemSelected(MenuItem item) {
        if (mActive != null) {
            for (int i=0; i<mAdded.size(); i++) {
                Fragment f = mAdded.get(i);
                if (f != null && !f.mHidden && f.mHasMenu) {
                    if (f.onOptionsItemSelected(item)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
    public void dispatchOptionsMenuClosed(Menu menu) {
        if (mActive != null) {
            for (int i=0; i<mAdded.size(); i++) {
                Fragment f = mAdded.get(i);
                if (f != null && !f.mHidden && f.mHasMenu) {
                    f.onOptionsMenuClosed(menu);
                }
            }
        }
    }
    
    public static int reverseTransit(int transit) {
        int rev = 0;
        switch (transit) {
Loading