ActionMenuView.java revision 04c0d4607897157f01c908475fa0c6d7301cf7e5
196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell/*
296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Copyright (C) 2010 The Android Open Source Project
396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * you may not use this file except in compliance with the License.
696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * You may obtain a copy of the License at
796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell *
1096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * Unless required by applicable law or agreed to in writing, software
1196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
1296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * See the License for the specific language governing permissions and
1496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell * limitations under the License.
1596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */
16fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellpackage android.widget;
1796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
1896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.content.Context;
198028dd32a4a04154050220dd0693583d5b750330Adam Powellimport android.content.res.Configuration;
2096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellimport android.util.AttributeSet;
213d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viveretteimport android.view.ContextThemeWrapper;
226b336f835d637853800b94689375a03f337139a4Adam Powellimport android.view.Gravity;
23fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport android.view.Menu;
24e43340c80dc66c45edc793ecd0343774aa34d108Adam Powellimport android.view.MenuItem;
25cf78b3e5101349fdddbde14b3a55140f9562ae66Adam Powellimport android.view.View;
26640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powellimport android.view.ViewDebug;
277ade1be822ed05a143b059319dccd5e9f623b56dAdam Powellimport android.view.ViewGroup;
287bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powellimport android.view.accessibility.AccessibilityEvent;
29fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.ActionMenuItemView;
30fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuBuilder;
31fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuItemImpl;
3204c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powellimport com.android.internal.view.menu.MenuPresenter;
33fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuView;
3496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell/**
36fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * ActionMenuView is a presentation of a series of menu options as a View. It provides
37fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * several top level options as action buttons while spilling remaining options over as
38fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * items in an overflow menu. This allows applications to present packs of actions inline with
39fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * specific or repeating content.
4096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */
4196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellpublic class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
4296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private static final String TAG = "ActionMenuView";
4396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
4435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    static final int MIN_CELL_SIZE = 56; // dips
45be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell    static final int GENERATED_ITEM_PADDING = 4; // dips
4635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
4796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private MenuBuilder mMenu;
487ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
493d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /** Context against which to inflate popup menus. */
503d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private Context mPopupContext;
513d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
523d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /** Theme resource against which to inflate popup menus. */
533d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private int mPopupTheme;
543d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
558028dd32a4a04154050220dd0693583d5b750330Adam Powell    private boolean mReserveOverflow;
56696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private ActionMenuPresenter mPresenter;
5704c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    private MenuPresenter.Callback mActionMenuPresenterCallback;
58640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    private boolean mFormatItems;
5989b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell    private int mFormatItemsWidth;
6035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private int mMinCellSize;
61be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell    private int mGeneratedItemPadding;
628515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
63e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private OnMenuItemClickListener mOnMenuItemClickListener;
64e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
6596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context) {
6696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        this(context, null);
6796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
6896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
6996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context, AttributeSet attrs) {
7096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        super(context, attrs);
71f16888f1e849b0bc0b9c17e5f833c4e2cd54c382Adam Powell        setBaselineAligned(false);
72be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final float density = context.getResources().getDisplayMetrics().density;
73be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mMinCellSize = (int) (MIN_CELL_SIZE * density);
74be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
753d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupContext = context;
763d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupTheme = 0;
77773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
78773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
793d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
803d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * Specifies the theme to use when inflating popup menus. By default, uses
813d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * the same theme as the action menu view itself.
823d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *
833d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param resId theme used to inflate popup menus
843d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #getPopupTheme()
853d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
863d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public void setPopupTheme(int resId) {
873d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        if (mPopupTheme != resId) {
883d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mPopupTheme = resId;
893d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            if (resId == 0) {
903d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = mContext;
913d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            } else {
923d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = new ContextThemeWrapper(mContext, resId);
933d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            }
943d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        }
953d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
963d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
973d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
983d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @return resource identifier of the theme used to inflate popup menus, or
993d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *         0 if menus are inflated against the action menu view theme
1003d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #setPopupTheme(int)
1013d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
1023d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public int getPopupTheme() {
1033d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        return mPopupTheme;
1043d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
1053d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
1063d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
1073d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param presenter Menu presenter used to display popup menu
1083d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @hide
1093d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
110696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void setPresenter(ActionMenuPresenter presenter) {
111696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter = presenter;
112e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        mPresenter.setMenuView(this);
113696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
114696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
1156c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    @Override
116773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    public void onConfigurationChanged(Configuration newConfig) {
1178515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onConfigurationChanged(newConfig);
118696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.updateMenuView(false);
1196c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
120696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenter != null && mPresenter.isOverflowMenuShowing()) {
121696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.hideOverflowMenu();
122696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.showOverflowMenu();
1236c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        }
124773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
125773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
126e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
127e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        mOnMenuItemClickListener = listener;
128e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
129e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
1308515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    @Override
131640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
13235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // If we've been given an exact size to match, apply special formatting during layout.
13389b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        final boolean wasFormatted = mFormatItems;
13435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
13589b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
13689b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (wasFormatted != mFormatItems) {
13789b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = 0; // Reset this when switching modes
13889b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        }
13989b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
14089b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Special formatting can change whether items can fit as action buttons.
14189b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Kick the menu and update presenters when this changes.
142da9710806bc7874b8c553f4daf9cf14f35ae1b07Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
14389b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
14489b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = widthSize;
145640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mMenu.onItemsChanged(true);
146640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
14735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
148e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        final int childCount = getChildCount();
149e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        if (mFormatItems && childCount > 0) {
15035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
15135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        } else {
15275d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            // Previous measurement at exact format may have set margins - reset them.
15375d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            for (int i = 0; i < childCount; i++) {
15475d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final View child = getChildAt(i);
15575d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
15675d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                lp.leftMargin = lp.rightMargin = 0;
15775d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            }
15835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
15935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
16035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
16135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
16335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // We already know the width mode is EXACTLY if we're here.
16435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
16535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
16635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
16735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int widthPadding = getPaddingLeft() + getPaddingRight();
16935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightPadding = getPaddingTop() + getPaddingBottom();
17035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
171fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding,
172fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell                ViewGroup.LayoutParams.WRAP_CONTENT);
173367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell
17435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        widthSize -= widthPadding;
17535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
17635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide the view into cells.
17735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellCount = widthSize / mMinCellSize;
17835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSizeRemaining = widthSize % mMinCellSize;
1793bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
1803bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        if (cellCount == 0) {
1813bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            // Give up, nothing fits.
1823bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            setMeasuredDimension(widthSize, 0);
1833bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            return;
1843bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        }
1853bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
18635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
18735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
18835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int cellsRemaining = cellCount;
18935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxChildHeight = 0;
19035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxCellsUsed = 0;
191160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int expandableItemCount = 0;
19214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        int visibleItemCount = 0;
19314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        boolean hasOverflow = false;
19435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
19614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        long smallestItemsAt = 0;
19735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childCount = getChildCount();
19935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        for (int i = 0; i < childCount; i++) {
20035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final View child = getChildAt(i);
20114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (child.getVisibility() == GONE) continue;
20214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
203be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            final boolean isGeneratedItem = child instanceof ActionMenuItemView;
20414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            visibleItemCount++;
20514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
206be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (isGeneratedItem) {
207be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // Reset padding for generated menu item views; it may change below
208be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // and views are recycled.
209be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
210be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            }
211be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
21235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
21335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.expanded = false;
21435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.extraPixels = 0;
21535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.cellsUsed = 0;
216160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            lp.expandable = false;
21714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.leftMargin = 0;
21814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.rightMargin = 0;
219be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
22035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Overflow always gets 1 cell. No more, no less.
22235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
22335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
225367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                    itemHeightSpec, heightPadding);
22635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
228160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            if (lp.expandable) expandableItemCount++;
22914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (lp.isOverflowButton) hasOverflow = true;
23035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
23135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining -= cellsUsed;
23235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
23314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (cellsUsed == 1) smallestItemsAt |= (1 << i);
23435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
23535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
236be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // When we have overflow and a single expanded (text) item, we want to try centering it
237be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // visually in the available space even though overflow consumes some of it.
238be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
239be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
24035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide space for remaining cells if we have items that can expand.
24135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Try distributing whole leftover cells to smaller items first.
24235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
24335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean needsExpansion = false;
244160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        while (expandableItemCount > 0 && cellsRemaining > 0) {
24535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCells = Integer.MAX_VALUE;
24635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            long minCellsAt = 0; // Bit locations are indices of relevant child views
24735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCellsItemCount = 0;
24835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
24935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
25035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
25135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Don't try to expand items that shouldn't.
253160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell                if (!lp.expandable) continue;
25435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Mark indices of children that can receive an extra cell.
25635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (lp.cellsUsed < minCells) {
25735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCells = lp.cellsUsed;
25835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt = 1 << i;
25935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount = 1;
26035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                } else if (lp.cellsUsed == minCells) {
26135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt |= 1 << i;
26235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount++;
26335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                }
26435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
26535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
26635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Items that get expanded will always be in the set of smallest items when we're done.
26714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            smallestItemsAt |= minCellsAt;
26835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
269be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
27035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
271be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            // We have enough cells, all minimum size items will be incremented.
272be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            minCells++;
273be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
274be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            for (int i = 0; i < childCount; i++) {
27535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
27635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
277be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if ((minCellsAt & (1 << i)) == 0) {
278be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // If this item is already at our small item count, mark it for later.
279be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
280be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    continue;
281be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
282be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
283be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
284be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // Add padding to this item such that it centers.
285be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
286be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
28735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.cellsUsed++;
28835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.expanded = true;
28935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                cellsRemaining--;
29035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
29135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            needsExpansion = true;
29335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
29435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide any space left that wouldn't divide along cell boundaries
29614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // evenly among the smallest items
29714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
29814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final boolean singleItem = !hasOverflow && visibleItemCount == 1;
29914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (cellsRemaining > 0 && smallestItemsAt != 0 &&
300be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
30114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            float expandCount = Long.bitCount(smallestItemsAt);
30214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
30314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (!singleItem) {
30414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                // The items at the far edges may only expand by half in order to pin to either side.
30514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & 1) != 0) {
306be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
307be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
30814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
30914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
310be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
311be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
31214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
31314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            }
31435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
3153bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            final int extraPixels = expandCount > 0 ?
3163bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell                    (int) (cellsRemaining * cellSize / expandCount) : 0;
31735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
31835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
31914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << i)) == 0) continue;
32035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
32135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
32235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
32314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if (child instanceof ActionMenuItemView) {
32414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If this is one of our views, expand and measure at the larger size.
32514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
32614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
327be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (i == 0 && !lp.preventEdgeOffset) {
32814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // First item gets part of its new padding pushed out of sight.
32914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // The last item will get this implicitly from layout.
33014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = -extraPixels / 2;
33114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
33214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else if (lp.isOverflowButton) {
33414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
33514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
33614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.rightMargin = -extraPixels / 2;
33714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else {
33914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If we don't know what it is, give it some margins instead
34014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // and let it center within its space. We still want to pin
34114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // against the edges.
34214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != 0) {
34314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = extraPixels / 2;
34414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != childCount - 1) {
34614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.rightMargin = extraPixels / 2;
34714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
34935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
35035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining = 0;
35235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
35335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Remeasure any items that have had extra space allocated to them.
35535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (needsExpansion) {
35635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
35735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
35835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
35935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (!lp.expanded) continue;
36135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int width = lp.cellsUsed * cellSize + lp.extraPixels;
363367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
364367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                        itemHeightSpec);
36535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
36635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
36735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (heightMode != MeasureSpec.EXACTLY) {
36935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            heightSize = maxChildHeight;
37035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
37135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        setMeasuredDimension(widthSize, heightSize);
37335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
37435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    /**
37635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * Measure a child view to fit within cell-based formatting. The child's width
37735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * will be measured to a whole multiple of cellSize.
37835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
379160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell     * <p>Sets the expandable and cellsUsed fields of LayoutParams.
38035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
38135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param child Child to measure
38235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellSize Size of one cell
38335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellsRemaining Number of cells remaining that this view can expand to fill
38435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightMeasureSpec MeasureSpec used by the parent view
38535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightPadding Padding present in the parent view
38635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @return Number of cells this child was measured to occupy
38735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     */
38835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    static int measureChildForCells(View child, int cellSize, int cellsRemaining,
38935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int parentHeightMeasureSpec, int parentHeightPadding) {
39035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
39135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
39235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) -
39335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                parentHeightPadding;
39435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
39535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
39635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
397a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
398a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell                (ActionMenuItemView) child : null;
399a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean hasText = itemView != null && itemView.hasText();
400a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell
401160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int cellsUsed = 0;
402a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) {
40335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int childWidthSpec = MeasureSpec.makeMeasureSpec(
40435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    cellSize * cellsRemaining, MeasureSpec.AT_MOST);
40535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            child.measure(childWidthSpec, childHeightSpec);
40635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
40735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int measuredWidth = child.getMeasuredWidth();
40835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsUsed = measuredWidth / cellSize;
40935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            if (measuredWidth % cellSize != 0) cellsUsed++;
410a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell            if (hasText && cellsUsed < 2) cellsUsed = 2;
41135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
412160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
413a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean expandable = !lp.isOverflowButton && hasText;
414160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        lp.expandable = expandable;
415160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
41635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        lp.cellsUsed = cellsUsed;
41735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int targetWidth = cellsUsed * cellSize;
41835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
41935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                childHeightSpec);
42035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return cellsUsed;
421640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
422640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
423640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
424640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
425640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        if (!mFormatItems) {
426640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super.onLayout(changed, left, top, right, bottom);
427640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            return;
428640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
429640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
430640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int childCount = getChildCount();
431640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int midVertical = (top + bottom) / 2;
432640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int dividerWidth = getDividerWidth();
433640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int overflowWidth = 0;
434640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowWidth = 0;
435640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowCount = 0;
436640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
43735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean hasOverflow = false;
4380762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        final boolean isLayoutRtl = isLayoutRtl();
439640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        for (int i = 0; i < childCount; i++) {
440640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            final View v = getChildAt(i);
441640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (v.getVisibility() == GONE) {
442640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                continue;
443640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
444640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
445640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            LayoutParams p = (LayoutParams) v.getLayoutParams();
446640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (p.isOverflowButton) {
447640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                overflowWidth = v.getMeasuredWidth();
448640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
449640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    overflowWidth += dividerWidth;
450640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
451640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
452640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int height = v.getMeasuredHeight();
4530762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int r;
4540762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int l;
4550762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (isLayoutRtl) {
4560762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = getPaddingLeft() + p.leftMargin;
4570762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = l + overflowWidth;
4580762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                } else {
4590762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = getWidth() - getPaddingRight() - p.rightMargin;
4600762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = r - overflowWidth;
4610762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
462640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int t = midVertical - (height / 2);
463640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int b = t + height;
464640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                v.layout(l, t, r, b);
465640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
466640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                widthRemaining -= overflowWidth;
46735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                hasOverflow = true;
468640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            } else {
46935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
47035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                nonOverflowWidth += size;
47135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                widthRemaining -= size;
472640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
473640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    nonOverflowWidth += dividerWidth;
474640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
475640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                nonOverflowCount++;
476640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
477640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
478640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
47914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (childCount == 1 && !hasOverflow) {
48014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            // Center a single child
48114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final View v = getChildAt(0);
48214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int width = v.getMeasuredWidth();
48314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int height = v.getMeasuredHeight();
48414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int midHorizontal = (right - left) / 2;
48514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int l = midHorizontal - width / 2;
48614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int t = midVertical - height / 2;
48714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            v.layout(l, t, l + width, t + height);
48814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            return;
48914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        }
49014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
49135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
49214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
493640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
4940762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        if (isLayoutRtl) {
4950762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startRight = getWidth() - getPaddingRight();
4960762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
4970762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
4980762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
4990762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
5000762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
5010762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
5020762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio
5030762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= lp.rightMargin;
5040762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5050762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5060762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5070762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startRight - width, t, startRight, t + height);
5080762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= width + lp.leftMargin + spacerSize;
509640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
5100762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        } else {
5110762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startLeft = getPaddingLeft();
5120762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
5130762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
5140762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
5150762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
5160762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
5170762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
518640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
5190762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += lp.leftMargin;
5200762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5210762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5220762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5230762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startLeft, t, startLeft + width, t + height);
5240762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += width + lp.rightMargin + spacerSize;
5250762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            }
526640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
527640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
528640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
529640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
5308515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void onDetachedFromWindow() {
5318515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onDetachedFromWindow();
532e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        dismissPopupMenus();
5338028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
5348028dd32a4a04154050220dd0693583d5b750330Adam Powell
535fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
5368028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean isOverflowReserved() {
5378028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mReserveOverflow;
5387ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
539fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
540fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
541b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    public void setOverflowReserved(boolean reserveOverflow) {
542b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell        mReserveOverflow = reserveOverflow;
543b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    }
544f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell
5457ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
5467ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateDefaultLayoutParams() {
5477ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
5487ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell                LayoutParams.WRAP_CONTENT);
5496b336f835d637853800b94689375a03f337139a4Adam Powell        params.gravity = Gravity.CENTER_VERTICAL;
5507ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return params;
5517ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
5527ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
5537ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
55435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    public LayoutParams generateLayoutParams(AttributeSet attrs) {
55535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return new LayoutParams(getContext(), attrs);
55635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
55735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
55835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    @Override
5597ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
5608c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        if (p != null) {
5618c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            final LayoutParams result = p instanceof LayoutParams
5628c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    ? new LayoutParams((LayoutParams) p)
5638c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    : new LayoutParams(p);
5643f476b34049d062942eafcf48396f593e00bd324Adam Powell            if (result.gravity <= Gravity.NO_GRAVITY) {
5653f476b34049d062942eafcf48396f593e00bd324Adam Powell                result.gravity = Gravity.CENTER_VERTICAL;
5663f476b34049d062942eafcf48396f593e00bd324Adam Powell            }
5673f476b34049d062942eafcf48396f593e00bd324Adam Powell            return result;
5683f476b34049d062942eafcf48396f593e00bd324Adam Powell        }
5697ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return generateDefaultLayoutParams();
5707ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
57196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
572696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
573696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
57435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return p != null && p instanceof LayoutParams;
575696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
576696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
577fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
578640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public LayoutParams generateOverflowButtonLayoutParams() {
579640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        LayoutParams result = generateDefaultLayoutParams();
580640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        result.isOverflowButton = true;
581640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return result;
582640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
583640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
584fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
58596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public boolean invokeItem(MenuItemImpl item) {
58696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mMenu.performItemAction(item, 0);
58796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
58896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
589fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
59096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public int getWindowAnimations() {
59196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return 0;
59296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
59396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
594fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
595696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void initialize(MenuBuilder menu) {
59696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMenu = menu;
597f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell    }
598f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell
599fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
600fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * Returns the Menu object that this ActionMenuView is currently presenting.
601fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
602fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * <p>Applications should use this method to obtain the ActionMenuView's Menu object
603fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * and inflate or add content to it as necessary.</p>
604fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
605fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @return the Menu presented by this view
606fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
607fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    public Menu getMenu() {
608fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        if (mMenu == null) {
609fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            final Context context = getContext();
610fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mMenu = new MenuBuilder(context);
611e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            mMenu.setCallback(new MenuBuilderCallback());
612fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mPresenter = new ActionMenuPresenter(context);
61304c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell            mPresenter.setCallback(mActionMenuPresenterCallback != null
61404c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell                    ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
6153d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mMenu.addMenuPresenter(mPresenter, mPopupContext);
61607a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell            mPresenter.setMenuView(this);
617fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        }
618fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
619fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        return mMenu;
620fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    }
621fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
622fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
62304c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     * Must be called before the first call to getMenu()
62404c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     * @hide
62504c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     */
62604c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    public void setActionMenuPresenterCallback(MenuPresenter.Callback cb) {
62704c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell        mActionMenuPresenterCallback = cb;
62804c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    }
62904c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell
63004c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    /**
631e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Returns the current menu or null if one has not yet been configured.
632e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @hide Internal use only for action bar integration
633e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
634e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public MenuBuilder peekMenu() {
635e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mMenu;
636e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
637e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
638e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
639e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Show the overflow items from the associated menu.
640e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
641e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be shown, false otherwise
642e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
643e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean showOverflowMenu() {
644e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.showOverflowMenu();
645e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
646e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
647e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
648e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Hide the overflow items from the associated menu.
649e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
650e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be hidden, false otherwise
651e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
652e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean hideOverflowMenu() {
653e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.hideOverflowMenu();
654e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
655e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
656e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
657e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Check whether the overflow menu is currently showing. This may not reflect
658e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * a pending show operation in progress.
659e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
660e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the overflow menu is currently showing
661e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
662e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowing() {
663e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowing();
664e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
665e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
666e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /** @hide */
667e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowPending() {
668e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowPending();
669e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
670e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
671e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
672e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Dismiss any popups associated with this menu view.
673e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
674e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public void dismissPopupMenus() {
675e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        if (mPresenter != null) {
676e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell            mPresenter.dismissPopupMenus();
677e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        }
678e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
679e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
680e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
681fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public.
682fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
683696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
684696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean hasDividerBeforeChildAt(int childIndex) {
685825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        if (childIndex == 0) {
686825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton            return false;
687825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        }
688696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View childBefore = getChildAt(childIndex - 1);
689696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View child = getChildAt(childIndex);
690696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean result = false;
691696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) {
692696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) childBefore).needsDividerAfter();
6938028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
694696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex > 0 && child instanceof ActionMenuChildView) {
695696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) child).needsDividerBefore();
696be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        }
697be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return result;
698be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
699be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
7007bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7017bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell        return false;
7027bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    }
7037bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell
70407a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    /** @hide */
70507a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    public void setExpandedActionViewsExclusive(boolean exclusive) {
70607a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell        mPresenter.setExpandedActionViewsExclusive(exclusive);
70707a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    }
70807a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell
709e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    /**
710e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * Interface responsible for receiving menu item click events if the items themselves
711e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * do not have individual item click listeners.
712e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     */
713e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public interface OnMenuItemClickListener {
714e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        /**
715e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * This method will be invoked when a menu item is clicked if the item itself did
716e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * not already handle the event.
717e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         *
718e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @param item {@link MenuItem} that was clicked
719e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
720e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         */
721e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemClick(MenuItem item);
722e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
723e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
724e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class MenuBuilderCallback implements MenuBuilder.Callback {
725e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
726e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
727e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return mOnMenuItemClickListener != null &&
728e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell                    mOnMenuItemClickListener.onMenuItemClick(item);
729e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
730e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
731e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
732e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onMenuModeChange(MenuBuilder menu) {
733e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
734e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
735e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
736e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback {
737e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
738e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
739e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
740e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
741e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
742e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onOpenSubMenu(MenuBuilder subMenu) {
743e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return false;
744e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
745e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
746e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
747fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
748696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public interface ActionMenuChildView {
749696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerBefore();
750696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerAfter();
7518515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
752640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
753640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public static class LayoutParams extends LinearLayout.LayoutParams {
754fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
755640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
756640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public boolean isOverflowButton;
757fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
758fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
75935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
76035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int cellsUsed;
761fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
762fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
76335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
76435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int extraPixels;
765fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
766fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
767160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
768160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        public boolean expandable;
769fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
770fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
771be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        @ViewDebug.ExportedProperty(category = "layout")
772be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        public boolean preventEdgeOffset;
773160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
774fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
77535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public boolean expanded;
776640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
777640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
778640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(c, attrs);
779640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
780640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
7818c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        public LayoutParams(ViewGroup.LayoutParams other) {
7828c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            super(other);
7838c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        }
7848c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell
785640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(LayoutParams other) {
786640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super((LinearLayout.LayoutParams) other);
787640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = other.isOverflowButton;
788640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
789640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
790640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height) {
791640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
792640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = false;
793640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
794640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
795fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
796640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height, boolean isOverflowButton) {
797640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
798640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            this.isOverflowButton = isOverflowButton;
799640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
800640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
80196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell}
802