Ejemplo n.º 1
0
    @Override
    public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) {
      mExpandedActionView = item.getActionView();
      mExpandedHomeLayout.setIcon(mIcon.getConstantState().newDrawable(/* TODO getResources() */ ));
      mCurrentExpandedItem = item;
      if (mExpandedActionView.getParent() != ActionBarView.this) {
        addView(mExpandedActionView);
      }
      if (mExpandedHomeLayout.getParent() != ActionBarView.this) {
        addView(mExpandedHomeLayout);
      }
      mHomeLayout.setVisibility(GONE);
      if (mTitleLayout != null) mTitleLayout.setVisibility(GONE);
      if (mTabScrollView != null) mTabScrollView.setVisibility(GONE);
      if (mSpinner != null) mSpinner.setVisibility(GONE);
      if (mCustomNavView != null) mCustomNavView.setVisibility(GONE);
      requestLayout();
      item.setActionViewExpanded(true);

      if (mExpandedActionView instanceof CollapsibleActionView) {
        ((CollapsibleActionView) mExpandedActionView).onActionViewExpanded();
      }

      return true;
    }
Ejemplo n.º 2
0
  public boolean performItemAction(MenuItem item, int flags) {
    MenuItemImpl itemImpl = (MenuItemImpl) item;

    if (itemImpl == null || !itemImpl.isEnabled()) {
      return false;
    }

    boolean invoked = itemImpl.invoke();

    if (itemImpl.hasCollapsibleActionView()) {
      invoked |= itemImpl.expandActionView();
      if (invoked) close(true);
    } else if (item.hasSubMenu()) {
      close(false);

      final SubMenuBuilder subMenu = (SubMenuBuilder) item.getSubMenu();
      final ActionProvider provider = item.getActionProvider();
      if (provider != null && provider.hasSubMenu()) {
        provider.onPrepareSubMenu(subMenu);
      }
      invoked |= dispatchSubMenuSelected(subMenu);
      if (!invoked) close(true);
    } else {
      if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {
        close(true);
      }
    }

    return invoked;
  }
Ejemplo n.º 3
0
 @Override
 public void onClick(View v) {
   final MenuItemImpl item = mExpandedMenuPresenter.mCurrentExpandedItem;
   if (item != null) {
     item.collapseActionView();
   }
 }
Ejemplo n.º 4
0
  public SubMenu addSubMenu(int group, int id, int categoryOrder, CharSequence title) {
    final MenuItemImpl item = (MenuItemImpl) addInternal(group, id, categoryOrder, title);
    final SubMenuBuilder subMenu = new SubMenuBuilder(mContext, this, item);
    item.setSubMenu(subMenu);

    return subMenu;
  }
Ejemplo n.º 5
0
 public void collapseActionView() {
   final MenuItemImpl item =
       mExpandedMenuPresenter == null ? null : mExpandedMenuPresenter.mCurrentExpandedItem;
   if (item != null) {
     item.collapseActionView();
   }
 }
    private void setItem(MenuItem item) {
      item.setChecked(itemChecked)
          .setVisible(itemVisible)
          .setEnabled(itemEnabled)
          .setCheckable(itemCheckable >= 1)
          .setTitleCondensed(itemTitleCondensed)
          .setIcon(itemIconResId)
          .setAlphabeticShortcut(itemAlphabeticShortcut)
          .setNumericShortcut(itemNumericShortcut);

      if (itemShowAsAction >= 0) {
        item.setShowAsAction(itemShowAsAction);
      }

      if (itemListenerMethodName != null) {
        if (mContext.isRestricted()) {
          throw new IllegalStateException(
              "The android:onClick attribute cannot " + "be used within a restricted context");
        }
        item.setOnMenuItemClickListener(
            new InflatedOnMenuItemClickListener(mRealOwner, itemListenerMethodName));
      }

      if (itemCheckable >= 2) {
        if (item instanceof MenuItemImpl) {
          MenuItemImpl impl = (MenuItemImpl) item;
          impl.setExclusiveCheckable(true);
        } else {
          menu.setGroupCheckable(groupId, true, true);
        }
      }

      boolean actionViewSpecified = false;
      if (itemActionViewClassName != null) {
        View actionView =
            (View)
                newInstance(
                    itemActionViewClassName,
                    ACTION_VIEW_CONSTRUCTOR_SIGNATURE,
                    mActionViewConstructorArguments);
        item.setActionView(actionView);
        actionViewSpecified = true;
      }
      if (itemActionViewLayout > 0) {
        if (!actionViewSpecified) {
          item.setActionView(itemActionViewLayout);
          actionViewSpecified = true;
        } else {
          Log.w(
              LOG_TAG,
              "Ignoring attribute 'itemActionViewLayout'." + " Action view already specified.");
        }
      }
      if (itemActionProvider != null) {
        item.setActionProvider(itemActionProvider);
      }
    }
Ejemplo n.º 7
0
  public void setGroupEnabled(int group, boolean enabled) {
    final int N = mItems.size();

    for (int i = 0; i < N; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.getGroupId() == group) {
        item.setEnabled(enabled);
      }
    }
  }
Ejemplo n.º 8
0
  private static int findInsertIndex(ArrayList<MenuItemImpl> items, int ordering) {
    for (int i = items.size() - 1; i >= 0; i--) {
      MenuItemImpl item = items.get(i);
      if (item.getOrdering() <= ordering) {
        return i + 1;
      }
    }

    return 0;
  }
Ejemplo n.º 9
0
  public void setGroupCheckable(int group, boolean checkable, boolean exclusive) {
    final int N = mItems.size();

    for (int i = 0; i < N; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.getGroupId() == group) {
        item.setExclusiveCheckable(exclusive);
        item.setCheckable(checkable);
      }
    }
  }
Ejemplo n.º 10
0
  public int findItemIndex(int id) {
    final int size = size();

    for (int i = 0; i < size; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.getItemId() == id) {
        return i;
      }
    }

    return -1;
  }
Ejemplo n.º 11
0
  public boolean hasVisibleItems() {
    final int size = size();

    for (int i = 0; i < size; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.isVisible()) {
        return true;
      }
    }

    return false;
  }
Ejemplo n.º 12
0
  @Override
  public boolean onMenuItemClick(android.view.MenuItem item) {
    if (DEBUG) Log.d(TAG, "[mNativeItemListener.onMenuItemClick] item: " + item);

    final MenuItemImpl sherlockItem = mNativeItemMap.get(item);
    if (sherlockItem != null) {
      sherlockItem.invoke();
    } else {
      Log.e(TAG, "Options item \"" + item + "\" not found in mapping");
    }

    return true; // Do not allow continuation of native handling
  }
  @Override
  public void setShortcut(boolean showShortcut, char shortcutKey) {
    final int newVisibility =
        showShortcut && mItemData.shouldShowShortcut() ? View.VISIBLE : View.GONE;

    if (newVisibility == View.VISIBLE) {
      mShortcutView.setText(mItemData.getShortcutLabel());
    }

    if (mShortcutView.getVisibility() != newVisibility) {
      mShortcutView.setVisibility(newVisibility);
    }
  }
Ejemplo n.º 14
0
  void setExclusiveItemChecked(MenuItem item) {
    final int group = item.getGroupId();

    final int N = mItems.size();
    for (int i = 0; i < N; i++) {
      MenuItemImpl curItem = mItems.get(i);
      if (curItem.getGroupId() == group) {
        if (!curItem.isExclusiveCheckable()) continue;
        if (!curItem.isCheckable()) continue;

        // Check the item meant to be checked, uncheck the others (that are in the group)
        curItem.setCheckedInt(curItem == item);
      }
    }
  }
  @Override
  public void setIcon(Drawable icon) {
    final boolean showIcon = mItemData.shouldShowIcon() || mForceShowIcon;
    if (!showIcon && !mPreserveIconSpacing) {
      return;
    }

    if (mIconView == null && icon == null && !mPreserveIconSpacing) {
      return;
    }

    if (mIconView == null) {
      insertIconView();
    }

    if (icon != null || mPreserveIconSpacing) {
      mIconView.setImageDrawable(showIcon ? icon : null);

      if (mIconView.getVisibility() != View.VISIBLE) {
        mIconView.setVisibility(View.VISIBLE);
      }
    } else {
      mIconView.setVisibility(View.GONE);
    }
  }
Ejemplo n.º 16
0
  public void setGroupVisible(int group, boolean visible) {
    final int N = mItems.size();

    // We handle the notification of items being changed ourselves, so we use setVisibleInt rather
    // than setVisible and at the end notify of items being changed

    boolean changedAtLeastOneItem = false;
    for (int i = 0; i < N; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.getGroupId() == group) {
        if (item.setVisibleInt(visible)) changedAtLeastOneItem = true;
      }
    }

    if (changedAtLeastOneItem) onItemsChanged(true);
  }
Ejemplo n.º 17
0
  /** Adds an item to the menu. The other add methods funnel to this. */
  private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
    final int ordering = getOrdering(categoryOrder);

    final MenuItemImpl item =
        new MenuItemImpl(this, group, id, categoryOrder, ordering, title, mDefaultShowAsAction);

    if (mCurrentMenuInfo != null) {
      // Pass along the current menu info
      item.setMenuInfo(mCurrentMenuInfo);
    }

    mItems.add(findInsertIndex(mItems, ordering), item);
    onItemsChanged(true);

    return item;
  }
  @Override
  public void setCheckable(boolean checkable) {
    if (!checkable && mRadioButton == null && mCheckBox == null) {
      return;
    }

    // Depending on whether its exclusive check or not, the checkbox or
    // radio button will be the one in use (and the other will be
    // otherCompoundButton)
    final CompoundButton compoundButton;
    final CompoundButton otherCompoundButton;

    if (mItemData.isExclusiveCheckable()) {
      if (mRadioButton == null) {
        insertRadioButton();
      }
      compoundButton = mRadioButton;
      otherCompoundButton = mCheckBox;
    } else {
      if (mCheckBox == null) {
        insertCheckBox();
      }
      compoundButton = mCheckBox;
      otherCompoundButton = mRadioButton;
    }

    if (checkable) {
      compoundButton.setChecked(mItemData.isChecked());

      final int newVisibility = checkable ? View.VISIBLE : View.GONE;
      if (compoundButton.getVisibility() != newVisibility) {
        compoundButton.setVisibility(newVisibility);
      }

      // Make sure the other compound button isn't visible
      if (otherCompoundButton != null && otherCompoundButton.getVisibility() != View.GONE) {
        otherCompoundButton.setVisibility(View.GONE);
      }
    } else {
      if (mCheckBox != null) {
        mCheckBox.setVisibility(View.GONE);
      }
      if (mRadioButton != null) {
        mRadioButton.setVisibility(View.GONE);
      }
    }
  }
Ejemplo n.º 19
0
  public int findGroupIndex(int group, int start) {
    final int size = size();

    if (start < 0) {
      start = 0;
    }

    for (int i = start; i < size; i++) {
      final MenuItemImpl item = mItems.get(i);

      if (item.getGroupId() == group) {
        return i;
      }
    }

    return -1;
  }
Ejemplo n.º 20
0
  public MenuItem findItem(int id) {
    final int size = size();
    for (int i = 0; i < size; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.getItemId() == id) {
        return item;
      } else if (item.hasSubMenu()) {
        MenuItem possibleItem = item.getSubMenu().findItem(id);

        if (possibleItem != null) {
          return possibleItem;
        }
      }
    }

    return null;
  }
Ejemplo n.º 21
0
  ArrayList<MenuItemImpl> getVisibleItems() {
    if (!mIsVisibleItemsStale) return mVisibleItems;

    // Refresh the visible items
    mVisibleItems.clear();

    final int itemsSize = mItems.size();
    MenuItemImpl item;
    for (int i = 0; i < itemsSize; i++) {
      item = mItems.get(i);
      if (item.isVisible()) mVisibleItems.add(item);
    }

    mIsVisibleItemsStale = false;
    mIsActionItemsStale = true;

    return mVisibleItems;
  }
  @Override
  public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) {
    View actionView = item.getActionView();
    if (actionView == null || item.hasCollapsibleActionView()) {
      if (!(convertView instanceof ActionMenuItemView)) {
        convertView = null;
      }
      actionView = super.getItemView(item, convertView, parent);
    }
    actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);

    final ActionMenuView menuParent = (ActionMenuView) parent;
    final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
    if (!menuParent.checkLayoutParams(lp)) {
      actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
    }
    return actionView;
  }
 @Override
 public void initialize(MenuItemImpl itemData, int menuType) {
   mItemData = itemData;
   setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
   setTitle(itemData.getTitleForItemView(this));
   setCheckable(itemData.isCheckable());
   setShortcut(itemData.shouldShowShortcut(), itemData.getShortcut());
   setIcon(itemData.getIcon());
   setEnabled(itemData.isEnabled());
 }
Ejemplo n.º 24
0
  /*
   * This function will return all the menu and sub-menu items that can
   * be directly (the shortcut directly corresponds) and indirectly
   * (the ALT-enabled char corresponds to the shortcut) associated
   * with the keyCode.
   */
  @SuppressWarnings("deprecation")
  void findItemsWithShortcutForKey(List<MenuItemImpl> items, int keyCode, KeyEvent event) {
    final boolean qwerty = isQwertyMode();
    final int metaState = event.getMetaState();
    final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
    // Get the chars associated with the keyCode (i.e using any chording combo)
    final boolean isKeyCodeMapped = event.getKeyData(possibleChars);
    // The delete key is not mapped to '\b' so we treat it specially
    if (!isKeyCodeMapped && (keyCode != KeyEvent.KEYCODE_DEL)) {
      return;
    }

    // Look for an item whose shortcut is this key.
    final int N = mItems.size();
    for (int i = 0; i < N; i++) {
      MenuItemImpl item = mItems.get(i);
      if (item.hasSubMenu()) {
        ((MenuBuilder) item.getSubMenu()).findItemsWithShortcutForKey(items, keyCode, event);
      }
      final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
      if (((metaState & (KeyEvent.META_SHIFT_ON | KeyEvent.META_SYM_ON)) == 0)
          && (shortcutChar != 0)
          && (shortcutChar == possibleChars.meta[0]
              || shortcutChar == possibleChars.meta[2]
              || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL))
          && item.isEnabled()) {
        items.add(item);
      }
    }
  }
Ejemplo n.º 25
0
  /**
   * 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() {
    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();
      ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
      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 ActionButtonSubmenu(Context context, SubMenuBuilder subMenu) {
      super(context, subMenu);
      // UNUSED mSubMenu = subMenu;

      MenuItemImpl item = (MenuItemImpl) subMenu.getItem();
      if (!item.isActionButton()) {
        // Give a reasonable anchor to nested submenus.
        setAnchorView(mOverflowButton == null ? (View) mMenuView : mOverflowButton);
      }

      setCallback(mPopupPresenterCallback);

      boolean preserveIconSpacing = false;
      final int count = subMenu.size();
      for (int i = 0; i < count; i++) {
        MenuItem childItem = subMenu.getItem(i);
        if (childItem.isVisible() && childItem.getIcon() != null) {
          preserveIconSpacing = true;
          break;
        }
      }
      setForceShowIcon(preserveIconSpacing);
    }
Ejemplo n.º 27
0
  /*
   * We want to return the menu item associated with the key, but if there is no
   * ambiguity (i.e. there is only one menu item corresponding to the key) we want
   * to return it even if it's not an exact match; this allow the user to
   * _not_ use the ALT key for example, making the use of shortcuts slightly more
   * user-friendly. An example is on the G1, '!' and '1' are on the same key, and
   * in Gmail, Menu+1 will trigger Menu+! (the actual shortcut).
   *
   * On the other hand, if two (or more) shortcuts corresponds to the same key,
   * we have to only return the exact match.
   */
  @SuppressWarnings("deprecation")
  MenuItemImpl findItemWithShortcutForKey(int keyCode, KeyEvent event) {
    // Get all items that can be associated directly or indirectly with the keyCode
    ArrayList<MenuItemImpl> items = mTempShortcutItemList;
    items.clear();
    findItemsWithShortcutForKey(items, keyCode, event);

    if (items.isEmpty()) {
      return null;
    }

    final int metaState = event.getMetaState();
    final KeyCharacterMap.KeyData possibleChars = new KeyCharacterMap.KeyData();
    // Get the chars associated with the keyCode (i.e using any chording combo)
    event.getKeyData(possibleChars);

    // If we have only one element, we can safely returns it
    final int size = items.size();
    if (size == 1) {
      return items.get(0);
    }

    final boolean qwerty = isQwertyMode();
    // If we found more than one item associated with the key,
    // we have to return the exact match
    for (int i = 0; i < size; i++) {
      final MenuItemImpl item = items.get(i);
      final char shortcutChar = qwerty ? item.getAlphabeticShortcut() : item.getNumericShortcut();
      if ((shortcutChar == possibleChars.meta[0] && (metaState & KeyEvent.META_ALT_ON) == 0)
          || (shortcutChar == possibleChars.meta[2] && (metaState & KeyEvent.META_ALT_ON) != 0)
          || (qwerty && shortcutChar == '\b' && keyCode == KeyEvent.KEYCODE_DEL)) {
        return item;
      }
    }
    return null;
  }
  @Override
  public void setChecked(boolean checked) {
    CompoundButton compoundButton;

    if (mItemData.isExclusiveCheckable()) {
      if (mRadioButton == null) {
        insertRadioButton();
      }
      compoundButton = mRadioButton;
    } else {
      if (mCheckBox == null) {
        insertCheckBox();
      }
      compoundButton = mCheckBox;
    }

    compoundButton.setChecked(checked);
  }
Ejemplo n.º 29
0
    @Override
    public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) {
      // Do this before detaching the actionview from the hierarchy, in case
      // it needs to dismiss the soft keyboard, etc.
      if (mExpandedActionView instanceof CollapsibleActionView) {
        ((CollapsibleActionView) mExpandedActionView).onActionViewCollapsed();
      }

      removeView(mExpandedActionView);
      removeView(mExpandedHomeLayout);
      mExpandedActionView = null;
      if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0) {
        mHomeLayout.setVisibility(VISIBLE);
      }
      if ((mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0) {
        if (mTitleLayout == null) {
          initTitle();
        } else {
          mTitleLayout.setVisibility(VISIBLE);
        }
      }
      if (mTabScrollView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
        mTabScrollView.setVisibility(VISIBLE);
      }
      if (mSpinner != null && mNavigationMode == ActionBar.NAVIGATION_MODE_LIST) {
        mSpinner.setVisibility(VISIBLE);
      }
      if (mCustomNavView != null && (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
        mCustomNavView.setVisibility(VISIBLE);
      }
      mExpandedHomeLayout.setIcon(null);
      mCurrentExpandedItem = null;
      requestLayout();
      item.setActionViewExpanded(false);

      return true;
    }
  public boolean flagActionItems() {
    final ArrayList<MenuItemImpl> visibleItems = mMenu.getVisibleItems();
    final int itemsSize = visibleItems.size();
    int maxActions = mMaxItems;
    int widthLimit = mActionItemWidthLimit;
    final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    final ViewGroup parent = (ViewGroup) mMenuView;

    int requiredItems = 0;
    int requestedItems = 0;
    int firstActionWidth = 0;
    boolean hasOverflow = false;
    for (int i = 0; i < itemsSize; i++) {
      MenuItemImpl item = visibleItems.get(i);
      if (item.requiresActionButton()) {
        requiredItems++;
      } else if (item.requestsActionButton()) {
        requestedItems++;
      } else {
        hasOverflow = true;
      }
      if (mExpandedActionViewsExclusive && item.isActionViewExpanded()) {
        // Overflow everything if we have an expanded action view and we're
        // space constrained.
        maxActions = 0;
      }
    }

    // Reserve a spot for the overflow item if needed.
    if (mReserveOverflow && (hasOverflow || requiredItems + requestedItems > maxActions)) {
      maxActions--;
    }
    maxActions -= requiredItems;

    final SparseBooleanArray seenGroups = mActionButtonGroups;
    seenGroups.clear();

    int cellSize = 0;
    int cellsRemaining = 0;
    if (mStrictWidthLimit) {
      cellsRemaining = widthLimit / mMinCellSize;
      final int cellSizeRemaining = widthLimit % mMinCellSize;
      cellSize = mMinCellSize + cellSizeRemaining / cellsRemaining;
    }

    // Flag as many more requested items as will fit.
    for (int i = 0; i < itemsSize; i++) {
      MenuItemImpl item = visibleItems.get(i);

      if (item.requiresActionButton()) {
        View v = getItemView(item, mScrapActionButtonView, parent);
        if (mScrapActionButtonView == null) {
          mScrapActionButtonView = v;
        }
        if (mStrictWidthLimit) {
          cellsRemaining -=
              ActionMenuView.measureChildForCells(v, cellSize, cellsRemaining, querySpec, 0);
        } else {
          v.measure(querySpec, querySpec);
        }
        final int measuredWidth = v.getMeasuredWidth();
        widthLimit -= measuredWidth;
        if (firstActionWidth == 0) {
          firstActionWidth = measuredWidth;
        }
        final int groupId = item.getGroupId();
        if (groupId != 0) {
          seenGroups.put(groupId, true);
        }
        item.setIsActionButton(true);
      } else if (item.requestsActionButton()) {
        // Items in a group with other items that already have an action slot
        // can break the max actions rule, but not the width limit.
        final int groupId = item.getGroupId();
        final boolean inGroup = seenGroups.get(groupId);
        boolean isAction =
            (maxActions > 0 || inGroup)
                && widthLimit > 0
                && (!mStrictWidthLimit || cellsRemaining > 0);

        if (isAction) {
          View v = getItemView(item, mScrapActionButtonView, parent);
          if (mScrapActionButtonView == null) {
            mScrapActionButtonView = v;
          }
          if (mStrictWidthLimit) {
            final int cells =
                ActionMenuView.measureChildForCells(v, cellSize, cellsRemaining, querySpec, 0);
            cellsRemaining -= cells;
            if (cells == 0) {
              isAction = false;
            }
          } else {
            v.measure(querySpec, querySpec);
          }
          final int measuredWidth = v.getMeasuredWidth();
          widthLimit -= measuredWidth;
          if (firstActionWidth == 0) {
            firstActionWidth = measuredWidth;
          }

          if (mStrictWidthLimit) {
            isAction &= widthLimit >= 0;
          } else {
            // Did this push the entire first item past the limit?
            isAction &= widthLimit + firstActionWidth > 0;
          }
        }

        if (isAction && groupId != 0) {
          seenGroups.put(groupId, true);
        } else if (inGroup) {
          // We broke the width limit. Demote the whole group, they all overflow now.
          seenGroups.put(groupId, false);
          for (int j = 0; j < i; j++) {
            MenuItemImpl areYouMyGroupie = visibleItems.get(j);
            if (areYouMyGroupie.getGroupId() == groupId) {
              // Give back the action slot
              if (areYouMyGroupie.isActionButton()) maxActions++;
              areYouMyGroupie.setIsActionButton(false);
            }
          }
        }

        if (isAction) maxActions--;

        item.setIsActionButton(isAction);
      }
    }
    return true;
  }