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