ActionMenuView.java revision 3d0f21dab8d891b9aebdd5277348d549eeb843e6
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;
32fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powellimport com.android.internal.view.menu.MenuView;
3396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
3496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell/**
35fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * ActionMenuView is a presentation of a series of menu options as a View. It provides
36fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * several top level options as action buttons while spilling remaining options over as
37fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * items in an overflow menu. This allows applications to present packs of actions inline with
38fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell * specific or repeating content.
3996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell */
4096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powellpublic class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvoker, MenuView {
4196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private static final String TAG = "ActionMenuView";
4296675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
4335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    static final int MIN_CELL_SIZE = 56; // dips
44be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell    static final int GENERATED_ITEM_PADDING = 4; // dips
4535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
4696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    private MenuBuilder mMenu;
477ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
483d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /** Context against which to inflate popup menus. */
493d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private Context mPopupContext;
503d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
513d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /** Theme resource against which to inflate popup menus. */
523d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    private int mPopupTheme;
533d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
548028dd32a4a04154050220dd0693583d5b750330Adam Powell    private boolean mReserveOverflow;
55696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    private ActionMenuPresenter mPresenter;
56640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    private boolean mFormatItems;
5789b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell    private int mFormatItemsWidth;
5835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private int mMinCellSize;
59be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell    private int mGeneratedItemPadding;
608515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell
61e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private OnMenuItemClickListener mOnMenuItemClickListener;
62e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
6396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context) {
6496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        this(context, null);
6596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
6696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
6796675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public ActionMenuView(Context context, AttributeSet attrs) {
6896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        super(context, attrs);
69f16888f1e849b0bc0b9c17e5f833c4e2cd54c382Adam Powell        setBaselineAligned(false);
70be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final float density = context.getResources().getDisplayMetrics().density;
71be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mMinCellSize = (int) (MIN_CELL_SIZE * density);
72be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
733d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupContext = context;
743d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        mPopupTheme = 0;
75773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
76773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
773d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
783d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * Specifies the theme to use when inflating popup menus. By default, uses
793d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * the same theme as the action menu view itself.
803d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *
813d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param resId theme used to inflate popup menus
823d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #getPopupTheme()
833d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
843d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public void setPopupTheme(int resId) {
853d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        if (mPopupTheme != resId) {
863d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mPopupTheme = resId;
873d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            if (resId == 0) {
883d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = mContext;
893d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            } else {
903d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette                mPopupContext = new ContextThemeWrapper(mContext, resId);
913d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            }
923d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        }
933d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
943d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
953d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
963d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @return resource identifier of the theme used to inflate popup menus, or
973d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     *         0 if menus are inflated against the action menu view theme
983d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @see #setPopupTheme(int)
993d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
1003d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    public int getPopupTheme() {
1013d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette        return mPopupTheme;
1023d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    }
1033d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette
1043d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette    /**
1053d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @param presenter Menu presenter used to display popup menu
1063d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     * @hide
1073d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette     */
108696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void setPresenter(ActionMenuPresenter presenter) {
109696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter = presenter;
110e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        mPresenter.setMenuView(this);
111696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
112696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
1136c6f575423d6718c3ff322224c1520901ce881e1Adam Powell    @Override
114773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    public void onConfigurationChanged(Configuration newConfig) {
1158515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onConfigurationChanged(newConfig);
116696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        mPresenter.updateMenuView(false);
1176c6f575423d6718c3ff322224c1520901ce881e1Adam Powell
118696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (mPresenter != null && mPresenter.isOverflowMenuShowing()) {
119696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.hideOverflowMenu();
120696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            mPresenter.showOverflowMenu();
1216c6f575423d6718c3ff322224c1520901ce881e1Adam Powell        }
122773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell    }
123773b1b97fc0f01efc8cf1e17a1250a9b654b1b85Adam Powell
124e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
125e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        mOnMenuItemClickListener = listener;
126e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
127e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
1288515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    @Override
129640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
13035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // If we've been given an exact size to match, apply special formatting during layout.
13189b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        final boolean wasFormatted = mFormatItems;
13235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY;
13389b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
13489b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (wasFormatted != mFormatItems) {
13589b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = 0; // Reset this when switching modes
13689b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        }
13789b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell
13889b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Special formatting can change whether items can fit as action buttons.
13989b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        // Kick the menu and update presenters when this changes.
140da9710806bc7874b8c553f4daf9cf14f35ae1b07Adam Powell        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
14189b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell        if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) {
14289b09da7b3b1e69264d9ec710c66eb2f891b313eAdam Powell            mFormatItemsWidth = widthSize;
143640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            mMenu.onItemsChanged(true);
144640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
14535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
146e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        final int childCount = getChildCount();
147e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        if (mFormatItems && childCount > 0) {
14835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec);
14935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        } else {
15075d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            // Previous measurement at exact format may have set margins - reset them.
15175d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            for (int i = 0; i < childCount; i++) {
15275d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final View child = getChildAt(i);
15375d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
15475d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell                lp.leftMargin = lp.rightMargin = 0;
15575d022af1f24cf2d8a7551183ea5bbe943d25d21Adam Powell            }
15635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
15735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
15835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
15935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) {
16135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // We already know the width mode is EXACTLY if we're here.
16235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
16335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
16435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
16535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
16635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int widthPadding = getPaddingLeft() + getPaddingRight();
16735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int heightPadding = getPaddingTop() + getPaddingBottom();
16835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
169fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding,
170fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell                ViewGroup.LayoutParams.WRAP_CONTENT);
171367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell
17235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        widthSize -= widthPadding;
17335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
17435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide the view into cells.
17535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellCount = widthSize / mMinCellSize;
17635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSizeRemaining = widthSize % mMinCellSize;
1773bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
1783bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        if (cellCount == 0) {
1793bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            // Give up, nothing fits.
1803bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            setMeasuredDimension(widthSize, 0);
1813bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            return;
1823bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell        }
1833bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell
18435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int cellSize = mMinCellSize + cellSizeRemaining / cellCount;
18535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
18635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int cellsRemaining = cellCount;
18735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxChildHeight = 0;
18835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        int maxCellsUsed = 0;
189160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int expandableItemCount = 0;
19014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        int visibleItemCount = 0;
19114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        boolean hasOverflow = false;
19235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64.
19414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        long smallestItemsAt = 0;
19535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
19635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childCount = getChildCount();
19735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        for (int i = 0; i < childCount; i++) {
19835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final View child = getChildAt(i);
19914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (child.getVisibility() == GONE) continue;
20014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
201be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            final boolean isGeneratedItem = child instanceof ActionMenuItemView;
20214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            visibleItemCount++;
20314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
204be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (isGeneratedItem) {
205be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // Reset padding for generated menu item views; it may change below
206be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                // and views are recycled.
207be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0);
208be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            }
209be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
21035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final LayoutParams lp = (LayoutParams) child.getLayoutParams();
21135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.expanded = false;
21235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.extraPixels = 0;
21335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            lp.cellsUsed = 0;
214160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            lp.expandable = false;
21514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.leftMargin = 0;
21614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            lp.rightMargin = 0;
217be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText();
21835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
21935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Overflow always gets 1 cell. No more, no less.
22035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
22135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
223367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                    itemHeightSpec, heightPadding);
22435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
226160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell            if (lp.expandable) expandableItemCount++;
22714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (lp.isOverflowButton) hasOverflow = true;
22835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
22935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining -= cellsUsed;
23035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight());
23114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (cellsUsed == 1) smallestItemsAt |= (1 << i);
23235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
23335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
234be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // When we have overflow and a single expanded (text) item, we want to try centering it
235be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        // visually in the available space even though overflow consumes some of it.
236be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2;
237be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
23835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide space for remaining cells if we have items that can expand.
23935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Try distributing whole leftover cells to smaller items first.
24035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
24135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean needsExpansion = false;
242160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        while (expandableItemCount > 0 && cellsRemaining > 0) {
24335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCells = Integer.MAX_VALUE;
24435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            long minCellsAt = 0; // Bit locations are indices of relevant child views
24535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int minCellsItemCount = 0;
24635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
24735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
24835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
24935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Don't try to expand items that shouldn't.
251160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell                if (!lp.expandable) continue;
25235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
25335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                // Mark indices of children that can receive an extra cell.
25435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (lp.cellsUsed < minCells) {
25535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCells = lp.cellsUsed;
25635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt = 1 << i;
25735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount = 1;
25835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                } else if (lp.cellsUsed == minCells) {
25935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsAt |= 1 << i;
26035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    minCellsItemCount++;
26135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                }
26235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
26335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
26435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            // Items that get expanded will always be in the set of smallest items when we're done.
26514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            smallestItemsAt |= minCellsAt;
26635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
267be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop.
26835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
269be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            // We have enough cells, all minimum size items will be incremented.
270be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            minCells++;
271be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
272be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell            for (int i = 0; i < childCount; i++) {
27335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
27435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
275be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if ((minCellsAt & (1 << i)) == 0) {
276be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // If this item is already at our small item count, mark it for later.
277be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i;
278be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    continue;
279be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
280be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell
281be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) {
282be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    // Add padding to this item such that it centers.
283be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0);
284be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                }
28535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.cellsUsed++;
28635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                lp.expanded = true;
28735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                cellsRemaining--;
28835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
28935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            needsExpansion = true;
29135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
29235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
29335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Divide any space left that wouldn't divide along cell boundaries
29414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        // evenly among the smallest items
29514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
29614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final boolean singleItem = !hasOverflow && visibleItemCount == 1;
29714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (cellsRemaining > 0 && smallestItemsAt != 0 &&
298be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) {
29914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            float expandCount = Long.bitCount(smallestItemsAt);
30014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
30114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            if (!singleItem) {
30214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                // The items at the far edges may only expand by half in order to pin to either side.
30314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & 1) != 0) {
304be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams();
305be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
30614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
30714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << (childCount - 1))) != 0) {
308be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams());
309be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (!lp.preventEdgeOffset) expandCount -= 0.5f;
31014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
31114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            }
31235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
3133bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell            final int extraPixels = expandCount > 0 ?
3143bb421d5b85a8a99c408d16e4f80163a53bc0505Adam Powell                    (int) (cellsRemaining * cellSize / expandCount) : 0;
31535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
31635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
31714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if ((smallestItemsAt & (1 << i)) == 0) continue;
31835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
31935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
32035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
32114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                if (child instanceof ActionMenuItemView) {
32214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If this is one of our views, expand and measure at the larger size.
32314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
32414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
325be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell                    if (i == 0 && !lp.preventEdgeOffset) {
32614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // First item gets part of its new padding pushed out of sight.
32714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        // The last item will get this implicitly from layout.
32814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = -extraPixels / 2;
32914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
33014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else if (lp.isOverflowButton) {
33214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.extraPixels = extraPixels;
33314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.expanded = true;
33414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    lp.rightMargin = -extraPixels / 2;
33514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    needsExpansion = true;
33614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                } else {
33714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // If we don't know what it is, give it some margins instead
33814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // and let it center within its space. We still want to pin
33914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    // against the edges.
34014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != 0) {
34114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.leftMargin = extraPixels / 2;
34214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    if (i != childCount - 1) {
34414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                        lp.rightMargin = extraPixels / 2;
34514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                    }
34614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell                }
34735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
34835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
34935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsRemaining = 0;
35035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
35135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        // Remeasure any items that have had extra space allocated to them.
35335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (needsExpansion) {
35435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            for (int i = 0; i < childCount; i++) {
35535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final View child = getChildAt(i);
35635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final LayoutParams lp = (LayoutParams) child.getLayoutParams();
35735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
35835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                if (!lp.expanded) continue;
35935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int width = lp.cellsUsed * cellSize + lp.extraPixels;
361367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
362367ee326058bbee6fc179b8b1eb2174fe7ba8f45Adam Powell                        itemHeightSpec);
36335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            }
36435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
36535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
36635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        if (heightMode != MeasureSpec.EXACTLY) {
36735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            heightSize = maxChildHeight;
36835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
36935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        setMeasuredDimension(widthSize, heightSize);
37135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
37235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
37335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    /**
37435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * Measure a child view to fit within cell-based formatting. The child's width
37535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * will be measured to a whole multiple of cellSize.
37635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
377160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell     * <p>Sets the expandable and cellsUsed fields of LayoutParams.
37835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     *
37935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param child Child to measure
38035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellSize Size of one cell
38135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param cellsRemaining Number of cells remaining that this view can expand to fill
38235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightMeasureSpec MeasureSpec used by the parent view
38335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @param parentHeightPadding Padding present in the parent view
38435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     * @return Number of cells this child was measured to occupy
38535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell     */
38635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    static int measureChildForCells(View child, int cellSize, int cellsRemaining,
38735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            int parentHeightMeasureSpec, int parentHeightPadding) {
38835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final LayoutParams lp = (LayoutParams) child.getLayoutParams();
38935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
39035aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) -
39135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                parentHeightPadding;
39235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec);
39335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode);
39435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
395a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final ActionMenuItemView itemView = child instanceof ActionMenuItemView ?
396a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell                (ActionMenuItemView) child : null;
397a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean hasText = itemView != null && itemView.hasText();
398a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell
399160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        int cellsUsed = 0;
400a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) {
40135aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int childWidthSpec = MeasureSpec.makeMeasureSpec(
40235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                    cellSize * cellsRemaining, MeasureSpec.AT_MOST);
40335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            child.measure(childWidthSpec, childHeightSpec);
40435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
40535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            final int measuredWidth = child.getMeasuredWidth();
40635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            cellsUsed = measuredWidth / cellSize;
40735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell            if (measuredWidth % cellSize != 0) cellsUsed++;
408a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell            if (hasText && cellsUsed < 2) cellsUsed = 2;
40935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        }
410160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
411a7dec6d9734bdc3a9e39ffd357002e25c6fdc99bAdam Powell        final boolean expandable = !lp.isOverflowButton && hasText;
412160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        lp.expandable = expandable;
413160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
41435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        lp.cellsUsed = cellsUsed;
41535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int targetWidth = cellsUsed * cellSize;
41635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY),
41735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                childHeightSpec);
41835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return cellsUsed;
419640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
420640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
421640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
422640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
423640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        if (!mFormatItems) {
424640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super.onLayout(changed, left, top, right, bottom);
425640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            return;
426640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
427640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
428640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int childCount = getChildCount();
429640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int midVertical = (top + bottom) / 2;
430640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        final int dividerWidth = getDividerWidth();
431640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int overflowWidth = 0;
432640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowWidth = 0;
433640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int nonOverflowCount = 0;
434640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        int widthRemaining = right - left - getPaddingRight() - getPaddingLeft();
43535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        boolean hasOverflow = false;
4360762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        final boolean isLayoutRtl = isLayoutRtl();
437640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        for (int i = 0; i < childCount; i++) {
438640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            final View v = getChildAt(i);
439640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (v.getVisibility() == GONE) {
440640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                continue;
441640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
442640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
443640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            LayoutParams p = (LayoutParams) v.getLayoutParams();
444640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            if (p.isOverflowButton) {
445640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                overflowWidth = v.getMeasuredWidth();
446640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
447640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    overflowWidth += dividerWidth;
448640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
449640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
450640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int height = v.getMeasuredHeight();
4510762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int r;
4520762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int l;
4530762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (isLayoutRtl) {
4540762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = getPaddingLeft() + p.leftMargin;
4550762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = l + overflowWidth;
4560762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                } else {
4570762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    r = getWidth() - getPaddingRight() - p.rightMargin;
4580762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    l = r - overflowWidth;
4590762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
460640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int t = midVertical - (height / 2);
461640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                int b = t + height;
462640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                v.layout(l, t, r, b);
463640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
464640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                widthRemaining -= overflowWidth;
46535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                hasOverflow = true;
466640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            } else {
46735aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin;
46835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                nonOverflowWidth += size;
46935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell                widthRemaining -= size;
470640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                if (hasDividerBeforeChildAt(i)) {
471640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                    nonOverflowWidth += dividerWidth;
472640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                }
473640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell                nonOverflowCount++;
474640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
475640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
476640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
47714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        if (childCount == 1 && !hasOverflow) {
47814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            // Center a single child
47914b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final View v = getChildAt(0);
48014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int width = v.getMeasuredWidth();
48114b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int height = v.getMeasuredHeight();
48214b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int midHorizontal = (right - left) / 2;
48314b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int l = midHorizontal - width / 2;
48414b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            final int t = midVertical - height / 2;
48514b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            v.layout(l, t, l + width, t + height);
48614b7e2c1688914ba8b6854738981337d7c0653beAdam Powell            return;
48714b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        }
48814b7e2c1688914ba8b6854738981337d7c0653beAdam Powell
48935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1);
49014b7e2c1688914ba8b6854738981337d7c0653beAdam Powell        final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0);
491640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
4920762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        if (isLayoutRtl) {
4930762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startRight = getWidth() - getPaddingRight();
4940762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
4950762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
4960762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
4970762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
4980762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
4990762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
5000762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio
5010762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= lp.rightMargin;
5020762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5030762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5040762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5050762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startRight - width, t, startRight, t + height);
5060762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startRight -= width + lp.leftMargin + spacerSize;
507640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            }
5080762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio        } else {
5090762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            int startLeft = getPaddingLeft();
5100762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            for (int i = 0; i < childCount; i++) {
5110762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final View v = getChildAt(i);
5120762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                final LayoutParams lp = (LayoutParams) v.getLayoutParams();
5130762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                if (v.getVisibility() == GONE || lp.isOverflowButton) {
5140762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                    continue;
5150762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                }
516640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
5170762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += lp.leftMargin;
5180762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int width = v.getMeasuredWidth();
5190762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int height = v.getMeasuredHeight();
5200762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                int t = midVertical - height / 2;
5210762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                v.layout(startLeft, t, startLeft + width, t + height);
5220762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio                startLeft += width + lp.rightMargin + spacerSize;
5230762cec04fa5ce65a2adc6d70ea1396041b1a88dFabrice Di Meglio            }
524640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
525640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
526640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
527640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    @Override
5288515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    public void onDetachedFromWindow() {
5298515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell        super.onDetachedFromWindow();
530e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        dismissPopupMenus();
5318028dd32a4a04154050220dd0693583d5b750330Adam Powell    }
5328028dd32a4a04154050220dd0693583d5b750330Adam Powell
533fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
5348028dd32a4a04154050220dd0693583d5b750330Adam Powell    public boolean isOverflowReserved() {
5358028dd32a4a04154050220dd0693583d5b750330Adam Powell        return mReserveOverflow;
5367ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
537fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
538fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
539b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    public void setOverflowReserved(boolean reserveOverflow) {
540b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell        mReserveOverflow = reserveOverflow;
541b366bbae2b5a3009893ef64246e3430cea4b7736Adam Powell    }
542f0ad6e6eaf48ac8f4007232ad0a8511a7b5cfc0eAdam Powell
5437ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
5447ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateDefaultLayoutParams() {
5457ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
5467ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell                LayoutParams.WRAP_CONTENT);
5476b336f835d637853800b94689375a03f337139a4Adam Powell        params.gravity = Gravity.CENTER_VERTICAL;
5487ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return params;
5497ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
5507ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell
5517ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    @Override
55235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    public LayoutParams generateLayoutParams(AttributeSet attrs) {
55335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return new LayoutParams(getContext(), attrs);
55435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    }
55535aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell
55635aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell    @Override
5577ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
5588c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        if (p != null) {
5598c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            final LayoutParams result = p instanceof LayoutParams
5608c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    ? new LayoutParams((LayoutParams) p)
5618c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell                    : new LayoutParams(p);
5623f476b34049d062942eafcf48396f593e00bd324Adam Powell            if (result.gravity <= Gravity.NO_GRAVITY) {
5633f476b34049d062942eafcf48396f593e00bd324Adam Powell                result.gravity = Gravity.CENTER_VERTICAL;
5643f476b34049d062942eafcf48396f593e00bd324Adam Powell            }
5653f476b34049d062942eafcf48396f593e00bd324Adam Powell            return result;
5663f476b34049d062942eafcf48396f593e00bd324Adam Powell        }
5677ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell        return generateDefaultLayoutParams();
5687ade1be822ed05a143b059319dccd5e9f623b56dAdam Powell    }
56996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
570696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
571696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
57235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        return p != null && p instanceof LayoutParams;
573696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    }
574696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell
575fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
576640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public LayoutParams generateOverflowButtonLayoutParams() {
577640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        LayoutParams result = generateDefaultLayoutParams();
578640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        result.isOverflowButton = true;
579640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        return result;
580640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
581640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
582fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
58396675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public boolean invokeItem(MenuItemImpl item) {
58496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return mMenu.performItemAction(item, 0);
58596675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
58696675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
587fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
58896675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    public int getWindowAnimations() {
58996675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        return 0;
59096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell    }
59196675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell
592fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
593696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public void initialize(MenuBuilder menu) {
59496675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell        mMenu = menu;
595f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell    }
596f6148c53f93978af678cc0559a4417b608a33ae1Adam Powell
597fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
598fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * Returns the Menu object that this ActionMenuView is currently presenting.
599fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
600fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * <p>Applications should use this method to obtain the ActionMenuView's Menu object
601fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * and inflate or add content to it as necessary.</p>
602fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     *
603fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @return the Menu presented by this view
604fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
605fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    public Menu getMenu() {
606fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        if (mMenu == null) {
607fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            final Context context = getContext();
608fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mMenu = new MenuBuilder(context);
609e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            mMenu.setCallback(new MenuBuilderCallback());
610fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell            mPresenter = new ActionMenuPresenter(context);
611e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            mPresenter.setCallback(new ActionMenuPresenterCallback());
6123d0f21dab8d891b9aebdd5277348d549eeb843e6Alan Viverette            mMenu.addMenuPresenter(mPresenter, mPopupContext);
61307a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell            mPresenter.setMenuView(this);
614fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        }
615fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
616fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        return mMenu;
617fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    }
618fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
619fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /**
620e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Returns the current menu or null if one has not yet been configured.
621e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @hide Internal use only for action bar integration
622e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
623e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public MenuBuilder peekMenu() {
624e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mMenu;
625e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
626e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
627e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
628e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Show the overflow items from the associated menu.
629e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
630e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be shown, false otherwise
631e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
632e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean showOverflowMenu() {
633e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.showOverflowMenu();
634e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
635e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
636e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
637e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Hide the overflow items from the associated menu.
638e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
639e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the menu was able to be hidden, false otherwise
640e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
641e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean hideOverflowMenu() {
642e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.hideOverflowMenu();
643e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
644e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
645e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
646e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Check whether the overflow menu is currently showing. This may not reflect
647e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * a pending show operation in progress.
648e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     *
649e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * @return true if the overflow menu is currently showing
650e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
651e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowing() {
652e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowing();
653e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
654e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
655e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /** @hide */
656e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public boolean isOverflowMenuShowPending() {
657e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        return mPresenter != null && mPresenter.isOverflowMenuShowPending();
658e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
659e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
660e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
661e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     * Dismiss any popups associated with this menu view.
662e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell     */
663e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    public void dismissPopupMenus() {
664e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        if (mPresenter != null) {
665e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell            mPresenter.dismissPopupMenus();
666e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell        }
667e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    }
668e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell
669e021e6ed8931a0a8296af182fc9b0c76b64fb0c4Adam Powell    /**
670fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public.
671fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell     */
672696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    @Override
673696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    protected boolean hasDividerBeforeChildAt(int childIndex) {
674825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        if (childIndex == 0) {
675825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton            return false;
676825992f503439bc87d9d7e698a487f17b5acc243Jake Wharton        }
677696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View childBefore = getChildAt(childIndex - 1);
678696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        final View child = getChildAt(childIndex);
679696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        boolean result = false;
680696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) {
681696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) childBefore).needsDividerAfter();
6828028dd32a4a04154050220dd0693583d5b750330Adam Powell        }
683696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        if (childIndex > 0 && child instanceof ActionMenuChildView) {
684696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell            result |= ((ActionMenuChildView) child).needsDividerBefore();
685be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        }
686be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell        return result;
687be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell    }
688be4d68e7b238b8ee879de0481e39c40d3f1683b6Adam Powell
6897bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6907bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell        return false;
6917bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell    }
6927bc3ca0dc52be52ecad1c0de8c62a6a4bf8141caAdam Powell
69307a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    /** @hide */
69407a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    public void setExpandedActionViewsExclusive(boolean exclusive) {
69507a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell        mPresenter.setExpandedActionViewsExclusive(exclusive);
69607a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell    }
69707a74548ae5c1e064508cb1c79ac34de1142b240Adam Powell
698e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    /**
699e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * Interface responsible for receiving menu item click events if the items themselves
700e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     * do not have individual item click listeners.
701e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell     */
702e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    public interface OnMenuItemClickListener {
703e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        /**
704e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * This method will be invoked when a menu item is clicked if the item itself did
705e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * not already handle the event.
706e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         *
707e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @param item {@link MenuItem} that was clicked
708e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         * @return <code>true</code> if the event was handled, <code>false</code> otherwise.
709e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell         */
710e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemClick(MenuItem item);
711e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
712e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
713e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class MenuBuilderCallback implements MenuBuilder.Callback {
714e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
715e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
716e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return mOnMenuItemClickListener != null &&
717e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell                    mOnMenuItemClickListener.onMenuItemClick(item);
718e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
719e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
720e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
721e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onMenuModeChange(MenuBuilder menu) {
722e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
723e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
724e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
725e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback {
726e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
727e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
728e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
729e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
730e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        @Override
731e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        public boolean onOpenSubMenu(MenuBuilder subMenu) {
732e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell            return false;
733e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell        }
734e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell    }
735e43340c80dc66c45edc793ecd0343774aa34d108Adam Powell
736fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell    /** @hide */
737696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell    public interface ActionMenuChildView {
738696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerBefore();
739696cba573e651b0e4f18a4718627c8ccecb3bda0Adam Powell        public boolean needsDividerAfter();
7408515ee846bd76aee86ec5ddfcc4dd1e626dd999cAdam Powell    }
741640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
742640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    public static class LayoutParams extends LinearLayout.LayoutParams {
743fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
744640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
745640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public boolean isOverflowButton;
746fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
747fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
74835aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
74935aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int cellsUsed;
750fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
751fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
75235aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
75335aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public int extraPixels;
754fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
755fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
756160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        @ViewDebug.ExportedProperty(category = "layout")
757160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell        public boolean expandable;
758fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell
759fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
760be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        @ViewDebug.ExportedProperty(category = "layout")
761be3c329ebec083e5ff933bab6b6c501519ad2bffAdam Powell        public boolean preventEdgeOffset;
762160bb7fa60e8ece654e6ce999b6c16af50ee7357Adam Powell
763fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
76435aecd5884a5ccfe380903e39f30f468315e8f92Adam Powell        public boolean expanded;
765640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
766640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(Context c, AttributeSet attrs) {
767640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(c, attrs);
768640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
769640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
7708c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        public LayoutParams(ViewGroup.LayoutParams other) {
7718c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell            super(other);
7728c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell        }
7738c1b02e7592dd02f30750c56bf88c65f8acbd3c9Adam Powell
774640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(LayoutParams other) {
775640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super((LinearLayout.LayoutParams) other);
776640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = other.isOverflowButton;
777640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
778640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
779640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height) {
780640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
781640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            isOverflowButton = false;
782640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
783640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell
784fa18d182a3f37505940e73ae6cd76c2e939f7f7cAdam Powell        /** @hide */
785640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        public LayoutParams(int width, int height, boolean isOverflowButton) {
786640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            super(width, height);
787640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell            this.isOverflowButton = isOverflowButton;
788640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell        }
789640a66eac612b850b5dabd3b93bd94f83ed2d567Adam Powell    }
79096675b1df3969f2d313b68f60ed9fa36805db8ceAdam Powell}
791