/** * Closes the visible menu. * * @param allMenusAreClosing Whether the menus are completely closing (true), or whether there is * another menu coming in this menu's place (false). For example, if the menu is closing * because a sub menu is about to be shown, <var>allMenusAreClosing</var> is false. */ final void close(boolean allMenusAreClosing) { if (mIsClosing) return; mIsClosing = true; for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { presenter.onCloseMenu(this, allMenusAreClosing); } } mIsClosing = false; }
private void dispatchPresenterUpdate(boolean cleared) { if (mPresenters.isEmpty()) return; stopDispatchingItemsChanged(); for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { presenter.updateMenuView(cleared); } } startDispatchingItemsChanged(); }
private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) { if (mPresenters.isEmpty()) return false; boolean result = false; for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else if (!result) { result = presenter.onSubMenuSelected(subMenu); } } return result; }
private void dispatchRestoreInstanceState(Bundle state) { SparseArray<Parcelable> presenterStates = state.getSparseParcelableArray(PRESENTER_KEY); if (presenterStates == null || mPresenters.isEmpty()) return; for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { final int id = presenter.getId(); if (id > 0) { Parcelable parcel = presenterStates.get(id); if (parcel != null) { presenter.onRestoreInstanceState(parcel); } } } } }
/** * This method determines which menu items get to be 'action items' that will appear in an action * bar and which items should be 'overflow items' in a secondary menu. The rules are as follows: * * <p>Items are considered for inclusion in the order specified within the menu. There is a limit * of mMaxActionItems as a total count, optionally including the overflow menu button itself. This * is a soft limit; if an item shares a group ID with an item previously included as an action * item, the new item will stay with its group and become an action item itself even if it breaks * the max item count limit. This is done to limit the conceptual complexity of the items * presented within an action bar. Only a few unrelated concepts should be presented to the user * in this space, and groups are treated as a single concept. * * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This limit may * be broken by a single item that exceeds the remaining space, but no further items may be added. * If an item that is part of a group cannot fit within the remaining measured width, the entire * group will be demoted to overflow. This is done to ensure room for navigation and other * affordances in the action bar as well as reduce general UI clutter. * * <p>The space freed by demoting a full group cannot be consumed by future menu items. Once items * begin to overflow, all future items become overflow items as well. This is to avoid inadvertent * reordering that may break the app's intended design. */ public void flagActionItems() { // Important side effect: if getVisibleItems is stale it may refresh, // which can affect action items staleness. final ArrayList<MenuItemImpl> visibleItems = getVisibleItems(); if (!mIsActionItemsStale) { return; } // Presenters flag action items as needed. boolean flagged = false; for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { flagged |= presenter.flagActionItems(); } } if (flagged) { mActionItems.clear(); mNonActionItems.clear(); final int itemsSize = visibleItems.size(); for (int i = 0; i < itemsSize; i++) { MenuItemImpl item = visibleItems.get(i); if (item.isActionButton()) { mActionItems.add(item); } else { mNonActionItems.add(item); } } } else { // Nobody flagged anything, everything is a non-action item. // (This happens during a first pass with no action-item presenters.) mActionItems.clear(); mNonActionItems.clear(); mNonActionItems.addAll(getVisibleItems()); } mIsActionItemsStale = false; }
public boolean collapseItemActionView(MenuItemImpl item) { if (mPresenters.isEmpty() || mExpandedItem != item) return false; boolean collapsed = false; stopDispatchingItemsChanged(); for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else if ((collapsed = presenter.collapseItemActionView(this, item))) { break; } } startDispatchingItemsChanged(); if (collapsed) { mExpandedItem = null; } return collapsed; }
private void dispatchSaveInstanceState(Bundle outState) { if (mPresenters.isEmpty()) return; SparseArray<Parcelable> presenterStates = new SparseArray<Parcelable>(); for (WeakReference<MenuPresenter> ref : mPresenters) { final MenuPresenter presenter = ref.get(); if (presenter == null) { mPresenters.remove(ref); } else { final int id = presenter.getId(); if (id > 0) { final Parcelable state = presenter.onSaveInstanceState(); if (state != null) { presenterStates.put(id, state); } } } } outState.putSparseParcelableArray(PRESENTER_KEY, presenterStates); }
/** * Add a presenter to this menu. This will only hold a WeakReference; you do not need to * explicitly remove a presenter, but you can using {@link #removeMenuPresenter(MenuPresenter)}. * * @param presenter The presenter to add */ public void addMenuPresenter(MenuPresenter presenter) { mPresenters.add(new WeakReference<MenuPresenter>(presenter)); presenter.initForMenu(mContext, this); mIsActionItemsStale = true; }