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;
58c46125042493e66f7dfdccec24e3b0739600b194Adam Powell    private MenuBuilder.Callback mMenuBuilderCallback;
59640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    private boolean mFormatItems;
6089b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell    private int mFormatItemsWidth;
6135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private int mMinCellSize;
62be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell    private int mGeneratedItemPadding;
638515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
64e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private OnMenuItemClickListener mOnMenuItemClickListener;
65e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
6696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context) {
6796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        this(context, null);
6896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
6996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
7096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context, AttributeSet attrs) {
7196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        super(context, attrs);
72f16888f1e849b0bc0b9c17e5f833c4e2cd54c382Adam Powell        setBaselineAligned(false);
73be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final float density = context.getResources().getDisplayMetrics().density;
74be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mMinCellSize = (int) (MIN_CELL_SIZE * density);
75be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
763d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupContext = context;
773d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupTheme = 0;
78773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
79773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
803d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
813d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * Specifies the theme to use when inflating popup menus. By default, uses
823d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * the same theme as the action menu view itself.
833d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *
843d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param resId theme used to inflate popup menus
853d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #getPopupTheme()
863d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
873d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public void setPopupTheme(int resId) {
883d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        if (mPopupTheme != resId) {
893d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mPopupTheme = resId;
903d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            if (resId == 0) {
913d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = mContext;
923d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            } else {
933d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = new ContextThemeWrapper(mContext, resId);
943d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            }
953d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        }
963d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
973d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
983d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
993d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @return resource identifier of the theme used to inflate popup menus, or
1003d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *         0 if menus are inflated against the action menu view theme
1013d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #setPopupTheme(int)
1023d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
1033d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public int getPopupTheme() {
1043d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        return mPopupTheme;
1053d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
1063d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
1073d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
1083d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param presenter Menu presenter used to display popup menu
1093d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @hide
1103d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
111696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void setPresenter(ActionMenuPresenter presenter) {
112696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter = presenter;
113e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        mPresenter.setMenuView(this);
114696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
115696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
1166c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    @Override
117773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    public void onConfigurationChanged(Configuration newConfig) {
1188515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onConfigurationChanged(newConfig);
119696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.updateMenuView(false);
1206c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
121696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenter != null && mPresenter.isOverflowMenuShowing()) {
122696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.hideOverflowMenu();
123696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.showOverflowMenu();
1246c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        }
125773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
126773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
127e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
128e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        mOnMenuItemClickListener = listener;
129e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
130e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
1318515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    @Override
132640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
13335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // If we've been given an exact size to match, apply special formatting during layout.
13489b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        final boolean wasFormatted = mFormatItems;
13535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
13689b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
13789b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (wasFormatted != mFormatItems) {
13889b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = 0; // Reset this when switching modes
13989b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        }
14089b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
14189b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Special formatting can change whether items can fit as action buttons.
14289b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Kick the menu and update presenters when this changes.
143da9710806bc7874b8c553f4daf9cf14f35ae1b07Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
14489b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
14589b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = widthSize;
146640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mMenu.onItemsChanged(true);
147640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
14835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
149e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        final int childCount = getChildCount();
150e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        if (mFormatItems && childCount > 0) {
15135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
15235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        } else {
15375d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            // Previous measurement at exact format may have set margins - reset them.
15475d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            for (int i = 0; i < childCount; i++) {
15575d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final View child = getChildAt(i);
15675d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
15775d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                lp.leftMargin = lp.rightMargin = 0;
15875d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            }
15935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
16035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
16135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
16235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
16435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // We already know the width mode is EXACTLY if we're here.
16535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
16635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
16735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
16835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int widthPadding = getPaddingLeft() + getPaddingRight();
17035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightPadding = getPaddingTop() + getPaddingBottom();
17135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
172fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding,
173fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell                ViewGroup.LayoutParams.WRAP_CONTENT);
174367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell
17535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        widthSize -= widthPadding;
17635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
17735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide the view into cells.
17835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellCount = widthSize / mMinCellSize;
17935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSizeRemaining = widthSize % mMinCellSize;
1803bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
1813bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        if (cellCount == 0) {
1823bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            // Give up, nothing fits.
1833bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            setMeasuredDimension(widthSize, 0);
1843bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            return;
1853bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        }
1863bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
18735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
18835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
18935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int cellsRemaining = cellCount;
19035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxChildHeight = 0;
19135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxCellsUsed = 0;
192160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int expandableItemCount = 0;
19314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        int visibleItemCount = 0;
19414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        boolean hasOverflow = false;
19535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
19714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        long smallestItemsAt = 0;
19835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childCount = getChildCount();
20035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        for (int i = 0; i < childCount; i++) {
20135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final View child = getChildAt(i);
20214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (child.getVisibility() == GONE) continue;
20314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
204be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            final boolean isGeneratedItem = child instanceof ActionMenuItemView;
20514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            visibleItemCount++;
20614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
207be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (isGeneratedItem) {
208be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // Reset padding for generated menu item views; it may change below
209be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // and views are recycled.
210be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
211be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            }
212be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
21335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
21435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.expanded = false;
21535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.extraPixels = 0;
21635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.cellsUsed = 0;
217160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            lp.expandable = false;
21814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.leftMargin = 0;
21914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.rightMargin = 0;
220be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
22135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Overflow always gets 1 cell. No more, no less.
22335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
22435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
226367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                    itemHeightSpec, heightPadding);
22735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
229160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            if (lp.expandable) expandableItemCount++;
23014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (lp.isOverflowButton) hasOverflow = true;
23135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
23235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining -= cellsUsed;
23335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
23414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (cellsUsed == 1) smallestItemsAt |= (1 << i);
23535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
23635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
237be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // When we have overflow and a single expanded (text) item, we want to try centering it
238be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // visually in the available space even though overflow consumes some of it.
239be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
240be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
24135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide space for remaining cells if we have items that can expand.
24235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Try distributing whole leftover cells to smaller items first.
24335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
24435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean needsExpansion = false;
245160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        while (expandableItemCount > 0 && cellsRemaining > 0) {
24635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCells = Integer.MAX_VALUE;
24735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            long minCellsAt = 0; // Bit locations are indices of relevant child views
24835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCellsItemCount = 0;
24935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
25035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
25135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
25235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Don't try to expand items that shouldn't.
254160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell                if (!lp.expandable) continue;
25535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Mark indices of children that can receive an extra cell.
25735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (lp.cellsUsed < minCells) {
25835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCells = lp.cellsUsed;
25935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt = 1 << i;
26035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount = 1;
26135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                } else if (lp.cellsUsed == minCells) {
26235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt |= 1 << i;
26335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount++;
26435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                }
26535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
26635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
26735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Items that get expanded will always be in the set of smallest items when we're done.
26814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            smallestItemsAt |= minCellsAt;
26935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
270be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
27135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
272be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            // We have enough cells, all minimum size items will be incremented.
273be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            minCells++;
274be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
275be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            for (int i = 0; i < childCount; i++) {
27635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
27735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
278be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if ((minCellsAt & (1 << i)) == 0) {
279be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // If this item is already at our small item count, mark it for later.
280be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
281be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    continue;
282be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
283be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
284be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
285be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // Add padding to this item such that it centers.
286be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
287be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
28835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.cellsUsed++;
28935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.expanded = true;
29035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                cellsRemaining--;
29135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
29235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            needsExpansion = true;
29435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
29535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide any space left that wouldn't divide along cell boundaries
29714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // evenly among the smallest items
29814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
29914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final boolean singleItem = !hasOverflow && visibleItemCount == 1;
30014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (cellsRemaining > 0 && smallestItemsAt != 0 &&
301be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
30214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            float expandCount = Long.bitCount(smallestItemsAt);
30314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
30414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (!singleItem) {
30514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                // The items at the far edges may only expand by half in order to pin to either side.
30614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & 1) != 0) {
307be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
308be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
30914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
31014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
311be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
312be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
31314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
31414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            }
31535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
3163bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            final int extraPixels = expandCount > 0 ?
3173bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell                    (int) (cellsRemaining * cellSize / expandCount) : 0;
31835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
31935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
32014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << i)) == 0) continue;
32135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
32235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
32335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
32414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if (child instanceof ActionMenuItemView) {
32514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If this is one of our views, expand and measure at the larger size.
32614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
32714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
328be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (i == 0 && !lp.preventEdgeOffset) {
32914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // First item gets part of its new padding pushed out of sight.
33014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // The last item will get this implicitly from layout.
33114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = -extraPixels / 2;
33214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
33314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else if (lp.isOverflowButton) {
33514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
33614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
33714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.rightMargin = -extraPixels / 2;
33814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else {
34014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If we don't know what it is, give it some margins instead
34114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // and let it center within its space. We still want to pin
34214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // against the edges.
34314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != 0) {
34414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = extraPixels / 2;
34514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != childCount - 1) {
34714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.rightMargin = extraPixels / 2;
34814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
35035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
35135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining = 0;
35335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
35435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Remeasure any items that have had extra space allocated to them.
35635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (needsExpansion) {
35735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
35835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
35935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
36035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (!lp.expanded) continue;
36235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int width = lp.cellsUsed * cellSize + lp.extraPixels;
364367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
365367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                        itemHeightSpec);
36635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
36735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
36835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (heightMode != MeasureSpec.EXACTLY) {
37035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            heightSize = maxChildHeight;
37135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
37235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        setMeasuredDimension(widthSize, heightSize);
37435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
37535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    /**
37735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * Measure a child view to fit within cell-based formatting. The child's width
37835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * will be measured to a whole multiple of cellSize.
37935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
380160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell     * <p>Sets the expandable and cellsUsed fields of LayoutParams.
38135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
38235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param child Child to measure
38335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellSize Size of one cell
38435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellsRemaining Number of cells remaining that this view can expand to fill
38535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightMeasureSpec MeasureSpec used by the parent view
38635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightPadding Padding present in the parent view
38735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @return Number of cells this child was measured to occupy
38835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     */
38935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    static int measureChildForCells(View child, int cellSize, int cellsRemaining,
39035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int parentHeightMeasureSpec, int parentHeightPadding) {
39135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
39235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
39335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) -
39435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                parentHeightPadding;
39535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
39635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
39735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
398a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
399a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell                (ActionMenuItemView) child : null;
400a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean hasText = itemView != null && itemView.hasText();
401a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell
402160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int cellsUsed = 0;
403a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) {
40435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int childWidthSpec = MeasureSpec.makeMeasureSpec(
40535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    cellSize * cellsRemaining, MeasureSpec.AT_MOST);
40635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            child.measure(childWidthSpec, childHeightSpec);
40735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
40835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int measuredWidth = child.getMeasuredWidth();
40935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsUsed = measuredWidth / cellSize;
41035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            if (measuredWidth % cellSize != 0) cellsUsed++;
411a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell            if (hasText && cellsUsed < 2) cellsUsed = 2;
41235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
413160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
414a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean expandable = !lp.isOverflowButton && hasText;
415160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        lp.expandable = expandable;
416160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
41735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        lp.cellsUsed = cellsUsed;
41835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int targetWidth = cellsUsed * cellSize;
41935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
42035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                childHeightSpec);
42135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return cellsUsed;
422640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
423640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
424640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
425640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
426640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        if (!mFormatItems) {
427640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super.onLayout(changed, left, top, right, bottom);
428640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            return;
429640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
430640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
431640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int childCount = getChildCount();
4321970cfd4ef97a5a1b5dc385b114d615d858c359bChris Banes        final int midVertical = (bottom - top) / 2;
433640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int dividerWidth = getDividerWidth();
434640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int overflowWidth = 0;
435640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowWidth = 0;
436640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowCount = 0;
437640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
43835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean hasOverflow = false;
4390762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        final boolean isLayoutRtl = isLayoutRtl();
440640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        for (int i = 0; i < childCount; i++) {
441640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            final View v = getChildAt(i);
442640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (v.getVisibility() == GONE) {
443640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                continue;
444640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
445640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
446640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            LayoutParams p = (LayoutParams) v.getLayoutParams();
447640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (p.isOverflowButton) {
448640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                overflowWidth = v.getMeasuredWidth();
449640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
450640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    overflowWidth += dividerWidth;
451640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
452640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
453640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int height = v.getMeasuredHeight();
4540762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int r;
4550762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int l;
4560762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (isLayoutRtl) {
4570762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = getPaddingLeft() + p.leftMargin;
4580762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = l + overflowWidth;
4590762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                } else {
4600762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = getWidth() - getPaddingRight() - p.rightMargin;
4610762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = r - overflowWidth;
4620762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
463640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int t = midVertical - (height / 2);
464640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int b = t + height;
465640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                v.layout(l, t, r, b);
466640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
467640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                widthRemaining -= overflowWidth;
46835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                hasOverflow = true;
469640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            } else {
47035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
47135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                nonOverflowWidth += size;
47235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                widthRemaining -= size;
473640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
474640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    nonOverflowWidth += dividerWidth;
475640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
476640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                nonOverflowCount++;
477640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
478640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
479640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
48014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (childCount == 1 && !hasOverflow) {
48114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            // Center a single child
48214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final View v = getChildAt(0);
48314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int width = v.getMeasuredWidth();
48414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int height = v.getMeasuredHeight();
48514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int midHorizontal = (right - left) / 2;
48614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int l = midHorizontal - width / 2;
48714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int t = midVertical - height / 2;
48814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            v.layout(l, t, l + width, t + height);
48914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            return;
49014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        }
49114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
49235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
49314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
494640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
4950762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        if (isLayoutRtl) {
4960762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startRight = getWidth() - getPaddingRight();
4970762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
4980762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
4990762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
5000762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
5010762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
5020762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
5030762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio
5040762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= lp.rightMargin;
5050762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5060762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5070762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5080762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startRight - width, t, startRight, t + height);
5090762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= width + lp.leftMargin + spacerSize;
510640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
5110762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        } else {
5120762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startLeft = getPaddingLeft();
5130762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
5140762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
5150762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
5160762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
5170762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
5180762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
519640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
5200762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += lp.leftMargin;
5210762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5220762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5230762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5240762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startLeft, t, startLeft + width, t + height);
5250762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += width + lp.rightMargin + spacerSize;
5260762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            }
527640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
528640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
529640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
530640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
5318515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void onDetachedFromWindow() {
5328515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onDetachedFromWindow();
533e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        dismissPopupMenus();
5348028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
5358028dd32a4a04154050220dd0693583d5b750330Adam Powell
536fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
5378028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean isOverflowReserved() {
5388028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mReserveOverflow;
5397ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
540fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
541fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
542b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    public void setOverflowReserved(boolean reserveOverflow) {
543b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell        mReserveOverflow = reserveOverflow;
544b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    }
545f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell
5467ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
5477ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateDefaultLayoutParams() {
5487ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
5497ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell                LayoutParams.WRAP_CONTENT);
5506b336f835d637853800b94689375a03f337139a4Adam Powell        params.gravity = Gravity.CENTER_VERTICAL;
5517ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return params;
5527ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
5537ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
5547ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
55535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    public LayoutParams generateLayoutParams(AttributeSet attrs) {
55635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return new LayoutParams(getContext(), attrs);
55735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
55835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
55935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    @Override
5607ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
5618c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        if (p != null) {
5628c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            final LayoutParams result = p instanceof LayoutParams
5638c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    ? new LayoutParams((LayoutParams) p)
5648c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    : new LayoutParams(p);
5653f476b34049d062942eafcf48396f593e00bd324Adam Powell            if (result.gravity <= Gravity.NO_GRAVITY) {
5663f476b34049d062942eafcf48396f593e00bd324Adam Powell                result.gravity = Gravity.CENTER_VERTICAL;
5673f476b34049d062942eafcf48396f593e00bd324Adam Powell            }
5683f476b34049d062942eafcf48396f593e00bd324Adam Powell            return result;
5693f476b34049d062942eafcf48396f593e00bd324Adam Powell        }
5707ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return generateDefaultLayoutParams();
5717ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
57296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
573696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
574696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
57535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return p != null && p instanceof LayoutParams;
576696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
577696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
578fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
579640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public LayoutParams generateOverflowButtonLayoutParams() {
580640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        LayoutParams result = generateDefaultLayoutParams();
581640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        result.isOverflowButton = true;
582640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return result;
583640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
584640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
585fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
58696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public boolean invokeItem(MenuItemImpl item) {
58796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mMenu.performItemAction(item, 0);
58896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
58996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
590fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
59196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public int getWindowAnimations() {
59296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return 0;
59396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
59496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
595fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
596696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void initialize(MenuBuilder menu) {
59796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMenu = menu;
598f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell    }
599f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell
600fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
601fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * Returns the Menu object that this ActionMenuView is currently presenting.
602fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
603fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * <p>Applications should use this method to obtain the ActionMenuView's Menu object
604fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * and inflate or add content to it as necessary.</p>
605fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
606fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @return the Menu presented by this view
607fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
608fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    public Menu getMenu() {
609fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        if (mMenu == null) {
610fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            final Context context = getContext();
611fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mMenu = new MenuBuilder(context);
612e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            mMenu.setCallback(new MenuBuilderCallback());
613fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mPresenter = new ActionMenuPresenter(context);
614e8d153673bdbbb113559ad592ad8a4e92e8d0d7eAdam Powell            mPresenter.setReserveOverflow(true);
61504c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell            mPresenter.setCallback(mActionMenuPresenterCallback != null
61604c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell                    ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback());
6173d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mMenu.addMenuPresenter(mPresenter, mPopupContext);
61807a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell            mPresenter.setMenuView(this);
619fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        }
620fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
621fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        return mMenu;
622fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    }
623fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
624fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
62504c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     * Must be called before the first call to getMenu()
62604c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     * @hide
62704c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell     */
628c46125042493e66f7dfdccec24e3b0739600b194Adam Powell    public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) {
629c46125042493e66f7dfdccec24e3b0739600b194Adam Powell        mActionMenuPresenterCallback = pcb;
630c46125042493e66f7dfdccec24e3b0739600b194Adam Powell        mMenuBuilderCallback = mcb;
63104c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    }
63204c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell
63304c0d4607897157f01c908475fa0c6d7301cf7e5Adam Powell    /**
634e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Returns the current menu or null if one has not yet been configured.
635e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @hide Internal use only for action bar integration
636e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
637e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public MenuBuilder peekMenu() {
638e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mMenu;
639e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
640e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
641e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
642e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Show the overflow items from the associated menu.
643e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
644e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be shown, false otherwise
645e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
646e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean showOverflowMenu() {
647e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.showOverflowMenu();
648e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
649e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
650e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
651e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Hide the overflow items from the associated menu.
652e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
653e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be hidden, false otherwise
654e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
655e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean hideOverflowMenu() {
656e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.hideOverflowMenu();
657e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
658e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
659e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
660e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Check whether the overflow menu is currently showing. This may not reflect
661e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * a pending show operation in progress.
662e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
663e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the overflow menu is currently showing
664e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
665e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowing() {
666e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowing();
667e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
668e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
669e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /** @hide */
670e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowPending() {
671e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowPending();
672e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
673e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
674e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
675e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Dismiss any popups associated with this menu view.
676e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
677e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public void dismissPopupMenus() {
678e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        if (mPresenter != null) {
679e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell            mPresenter.dismissPopupMenus();
680e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        }
681e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
682e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
683e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
684fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public.
685fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
686696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
687696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean hasDividerBeforeChildAt(int childIndex) {
688825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        if (childIndex == 0) {
689825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton            return false;
690825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        }
691696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View childBefore = getChildAt(childIndex - 1);
692696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View child = getChildAt(childIndex);
693696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean result = false;
694696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) {
695696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) childBefore).needsDividerAfter();
6968028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
697696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex > 0 && child instanceof ActionMenuChildView) {
698696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) child).needsDividerBefore();
699be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        }
700be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return result;
701be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
702be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
7037bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
7047bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell        return false;
7057bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    }
7067bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell
70707a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    /** @hide */
70807a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    public void setExpandedActionViewsExclusive(boolean exclusive) {
70907a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell        mPresenter.setExpandedActionViewsExclusive(exclusive);
71007a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    }
71107a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell
712e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    /**
713e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * Interface responsible for receiving menu item click events if the items themselves
714e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * do not have individual item click listeners.
715e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     */
716e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public interface OnMenuItemClickListener {
717e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        /**
718e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * This method will be invoked when a menu item is clicked if the item itself did
719e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * not already handle the event.
720e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         *
721e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @param item {@link MenuItem} that was clicked
722e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
723e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         */
724e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemClick(MenuItem item);
725e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
726e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
727e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class MenuBuilderCallback implements MenuBuilder.Callback {
728e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
729e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
730e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return mOnMenuItemClickListener != null &&
731e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell                    mOnMenuItemClickListener.onMenuItemClick(item);
732e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
733e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
734e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
735e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onMenuModeChange(MenuBuilder menu) {
736c46125042493e66f7dfdccec24e3b0739600b194Adam Powell            if (mMenuBuilderCallback != null) {
737c46125042493e66f7dfdccec24e3b0739600b194Adam Powell                mMenuBuilderCallback.onMenuModeChange(menu);
738c46125042493e66f7dfdccec24e3b0739600b194Adam Powell            }
739e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
740e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
741e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
742e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback {
743e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
744e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
745e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
746e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
747e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
748e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onOpenSubMenu(MenuBuilder subMenu) {
749e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return false;
750e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
751e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
752e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
753fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
754696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public interface ActionMenuChildView {
755696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerBefore();
756696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerAfter();
7578515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
758640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
759640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public static class LayoutParams extends LinearLayout.LayoutParams {
760fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
761640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
762640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public boolean isOverflowButton;
763fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
764fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
76535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
76635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int cellsUsed;
767fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
768fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
76935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
77035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int extraPixels;
771fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
772fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
773160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
774160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        public boolean expandable;
775fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
776fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
777be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        @ViewDebug.ExportedProperty(category = "layout")
778be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        public boolean preventEdgeOffset;
779160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
780fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
78135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public boolean expanded;
782640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
783640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
784640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(c, attrs);
785640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
786640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
7878c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        public LayoutParams(ViewGroup.LayoutParams other) {
7888c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            super(other);
7898c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        }
7908c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell
791640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(LayoutParams other) {
792640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super((LinearLayout.LayoutParams) other);
793640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = other.isOverflowButton;
794640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
795640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
796640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height) {
797640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
798640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = false;
799640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
800640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
801fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
802640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height, boolean isOverflowButton) {
803640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
804640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            this.isOverflowButton = isOverflowButton;
805640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
806640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
80796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell}
808