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