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