1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/* 249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Copyright (C) 2014 The Android Open Source Project 3bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 4bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Licensed under the Apache License, Version 2.0 (the "License"); 5bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * you may not use this file except in compliance with the License. 6bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * You may obtain a copy of the License at 7bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 8bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * http://www.apache.org/licenses/LICENSE-2.0 9bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * 10bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Unless required by applicable law or agreed to in writing, software 11bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * distributed under the License is distributed on an "AS IS" BASIS, 12bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * See the License for the specific language governing permissions and 14bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * limitations under the License. 15bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 1649c78900da0d43140fb602431fb93212bd7f6c70Chris Banespackage android.support.v7.widget; 17bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context; 19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Configuration; 20b34bdc0555f758dccd9307ce696c5134f5ce5042Trevor Johnsimport android.os.Build; 2149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.ActionMenuItemView; 2249c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuBuilder; 2349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuItemImpl; 24c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banesimport android.support.v7.internal.view.menu.MenuPresenter; 2549c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.internal.view.menu.MenuView; 26a2c72b87007d10202c25e78e904938f770c6337dChris Banesimport android.support.v7.internal.widget.ViewUtils; 27bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.util.AttributeSet; 2849c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.ContextThemeWrapper; 29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.Gravity; 3049c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Menu; 3149c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.MenuItem; 32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View; 33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewDebug; 34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup; 35bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.accessibility.AccessibilityEvent; 36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/** 3849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * ActionMenuView is a presentation of a series of menu options as a View. It provides 3949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * several top level options as action buttons while spilling remaining options over as 4049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * items in an overflow menu. This allows applications to present packs of actions inline with 4149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * specific or repeating content. 42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 4349c78900da0d43140fb602431fb93212bd7f6c70Chris Banespublic class ActionMenuView extends LinearLayoutCompat implements MenuBuilder.ItemInvoker, 4449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MenuView { 45b34bdc0555f758dccd9307ce696c5134f5ce5042Trevor Johns 4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private static final String TAG = "ActionMenuView"; 47bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 4820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns static final int MIN_CELL_SIZE = 56; // dips 4920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns static final int GENERATED_ITEM_PADDING = 4; // dips 5020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 5120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private MenuBuilder mMenu; 52bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 5349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private Context mContext; 5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** Context against which to inflate popup menus. */ 5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private Context mPopupContext; 5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** Theme resource against which to inflate popup menus. */ 5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mPopupTheme; 6049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 6120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private boolean mReserveOverflow; 6220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private ActionMenuPresenter mPresenter; 63c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes private MenuPresenter.Callback mActionMenuPresenterCallback; 64c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes private MenuBuilder.Callback mMenuBuilderCallback; 6520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private boolean mFormatItems; 6620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private int mFormatItemsWidth; 6720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private int mMinCellSize; 6820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private int mGeneratedItemPadding; 6949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 7049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private OnMenuItemClickListener mOnMenuItemClickListener; 71bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 7220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public ActionMenuView(Context context) { 7320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns this(context, null); 74bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 75bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 7620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public ActionMenuView(Context context, AttributeSet attrs) { 7720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super(context, attrs); 7849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mContext = context; 7920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns setBaselineAligned(false); 8020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final float density = context.getResources().getDisplayMetrics().density; 8120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mMinCellSize = (int) (MIN_CELL_SIZE * density); 8220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density); 8349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupContext = context; 8449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupTheme = 0; 8549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 8620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 8749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 8849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Specifies the theme to use when inflating popup menus. By default, uses 8949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * the same theme as the action menu view itself. 9049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 9149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param resId theme used to inflate popup menus 9249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #getPopupTheme() 9349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 9449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setPopupTheme(int resId) { 9549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mPopupTheme != resId) { 9649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupTheme = resId; 9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (resId == 0) { 9849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupContext = mContext; 9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else { 10049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupContext = new ContextThemeWrapper(mContext, resId); 10149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 10249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 103bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 104bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 10549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 10649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return resource identifier of the theme used to inflate popup menus, or 10749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 0 if menus are inflated against the action menu view theme 10849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @see #setPopupTheme(int) 10949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 11049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public int getPopupTheme() { 11149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopupTheme; 112bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 113bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 11449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 11549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param presenter Menu presenter used to display popup menu 11649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @hide 11749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 11849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setPresenter(ActionMenuPresenter presenter) { 11949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter = presenter; 12049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter.setMenuView(this); 12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 122bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 12320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 12420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public void onConfigurationChanged(Configuration newConfig) { 12520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (Build.VERSION.SDK_INT >= 8) { 12620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super.onConfigurationChanged(newConfig); 12720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 128bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 12920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mPresenter.updateMenuView(false); 130bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 13120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (mPresenter != null && mPresenter.isOverflowMenuShowing()) { 13220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mPresenter.hideOverflowMenu(); 13320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mPresenter.showOverflowMenu(); 13420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 13520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 136bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 13749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setOnMenuItemClickListener(OnMenuItemClickListener listener) { 13849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mOnMenuItemClickListener = listener; 13949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 14049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 14120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 14220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 14320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // If we've been given an exact size to match, apply special formatting during layout. 14420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean wasFormatted = mFormatItems; 14520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mFormatItems = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; 146bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 14720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (wasFormatted != mFormatItems) { 14820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mFormatItemsWidth = 0; // Reset this when switching modes 14920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 150bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 15120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Special formatting can change whether items can fit as action buttons. 15220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Kick the menu and update presenters when this changes. 15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int widthSize = MeasureSpec.getSize(widthMeasureSpec); 15420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (mFormatItems && mMenu != null && widthSize != mFormatItemsWidth) { 15520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mFormatItemsWidth = widthSize; 15620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mMenu.onItemsChanged(true); 15720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 158bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 15949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int childCount = getChildCount(); 16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mFormatItems && childCount > 0) { 16120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns onMeasureExactFormat(widthMeasureSpec, heightMeasureSpec); 16220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } else { 16320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Previous measurement at exact format may have set margins - reset them. 16420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 16520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 16620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 16720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.leftMargin = lp.rightMargin = 0; 16820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 16920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super.onMeasure(widthMeasureSpec, heightMeasureSpec); 17020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 17120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 172bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 17320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns private void onMeasureExactFormat(int widthMeasureSpec, int heightMeasureSpec) { 17420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // We already know the width mode is EXACTLY if we're here. 17520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int heightMode = MeasureSpec.getMode(heightMeasureSpec); 17620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int widthSize = MeasureSpec.getSize(widthMeasureSpec); 17720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int heightSize = MeasureSpec.getSize(heightMeasureSpec); 178bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int widthPadding = getPaddingLeft() + getPaddingRight(); 18020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int heightPadding = getPaddingTop() + getPaddingBottom(); 181bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 18249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int itemHeightSpec = getChildMeasureSpec(heightMeasureSpec, heightPadding, 18349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ViewGroup.LayoutParams.WRAP_CONTENT); 184bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 18520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns widthSize -= widthPadding; 186bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 18720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Divide the view into cells. 18820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int cellCount = widthSize / mMinCellSize; 18920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int cellSizeRemaining = widthSize % mMinCellSize; 190bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 19120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (cellCount == 0) { 19220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Give up, nothing fits. 19320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns setMeasuredDimension(widthSize, 0); 19420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return; 19520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 196bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 19720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int cellSize = mMinCellSize + cellSizeRemaining / cellCount; 19820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 19920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int cellsRemaining = cellCount; 20020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int maxChildHeight = 0; 20120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int maxCellsUsed = 0; 20220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int expandableItemCount = 0; 20320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int visibleItemCount = 0; 20420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns boolean hasOverflow = false; 20520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 20620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // This is used as a bitfield to locate the smallest items present. Assumes childCount < 64. 20720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns long smallestItemsAt = 0; 20820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 20920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childCount = getChildCount(); 21020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 21120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 21249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (child.getVisibility() == GONE) continue; 21320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 21420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean isGeneratedItem = child instanceof ActionMenuItemView; 21520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns visibleItemCount++; 21620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 21720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (isGeneratedItem) { 21820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Reset padding for generated menu item views; it may change below 21920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // and views are recycled. 22020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns child.setPadding(mGeneratedItemPadding, 0, mGeneratedItemPadding, 0); 22120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 22320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 22420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expanded = false; 22520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.extraPixels = 0; 22620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.cellsUsed = 0; 22720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expandable = false; 22820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.leftMargin = 0; 22920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.rightMargin = 0; 23020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.preventEdgeOffset = isGeneratedItem && ((ActionMenuItemView) child).hasText(); 23120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 23220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Overflow always gets 1 cell. No more, no less. 23320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining; 23420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 23520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable, 23620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns itemHeightSpec, heightPadding); 23720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 23820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns maxCellsUsed = Math.max(maxCellsUsed, cellsUsed); 23949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.expandable) expandableItemCount++; 24049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.isOverflowButton) hasOverflow = true; 24120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 24220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns cellsRemaining -= cellsUsed; 24320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns maxChildHeight = Math.max(maxChildHeight, child.getMeasuredHeight()); 24449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (cellsUsed == 1) smallestItemsAt |= (1 << i); 245bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 246bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 24720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // When we have overflow and a single expanded (text) item, we want to try centering it 24820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // visually in the available space even though overflow consumes some of it. 24920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean centerSingleExpandedItem = hasOverflow && visibleItemCount == 2; 25020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 25120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Divide space for remaining cells if we have items that can expand. 25220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Try distributing whole leftover cells to smaller items first. 25320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 25420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns boolean needsExpansion = false; 25520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns while (expandableItemCount > 0 && cellsRemaining > 0) { 25620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int minCells = Integer.MAX_VALUE; 25720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns long minCellsAt = 0; // Bit locations are indices of relevant child views 25820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int minCellsItemCount = 0; 25920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 26020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 26120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 26220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 26320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Don't try to expand items that shouldn't. 26449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!lp.expandable) continue; 26520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 26620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Mark indices of children that can receive an extra cell. 26720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (lp.cellsUsed < minCells) { 26820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCells = lp.cellsUsed; 26920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCellsAt = 1 << i; 27020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCellsItemCount = 1; 27120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } else if (lp.cellsUsed == minCells) { 27220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCellsAt |= 1 << i; 27320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCellsItemCount++; 27420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 27520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 27620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 27720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Items that get expanded will always be in the set of smallest items when we're done. 27820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns smallestItemsAt |= minCellsAt; 27920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 28049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (minCellsItemCount > cellsRemaining) break; // Couldn't expand anything evenly. Stop. 28120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 28220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // We have enough cells, all minimum size items will be incremented. 28320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns minCells++; 28420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 28520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 28620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 28720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 28820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if ((minCellsAt & (1 << i)) == 0) { 28920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // If this item is already at our small item count, mark it for later. 29049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (lp.cellsUsed == minCells) smallestItemsAt |= 1 << i; 29120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns continue; 29220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 29320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 29420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (centerSingleExpandedItem && lp.preventEdgeOffset && cellsRemaining == 1) { 29520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Add padding to this item such that it centers. 29620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns child.setPadding(mGeneratedItemPadding + cellSize, 0, mGeneratedItemPadding, 0); 29720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 29820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.cellsUsed++; 29920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expanded = true; 30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns cellsRemaining--; 30120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 30220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 30320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns needsExpansion = true; 304bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 305bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 30620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Divide any space left that wouldn't divide along cell boundaries 30720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // evenly among the smallest items 30820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 30920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean singleItem = !hasOverflow && visibleItemCount == 1; 31020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (cellsRemaining > 0 && smallestItemsAt != 0 && 31120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns (cellsRemaining < visibleItemCount - 1 || singleItem || maxCellsUsed > 1)) { 31220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns float expandCount = Long.bitCount(smallestItemsAt); 31320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 31420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (!singleItem) { 31520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // The items at the far edges may only expand by half in order to pin to either side. 31620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if ((smallestItemsAt & 1) != 0) { 31720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams lp = (LayoutParams) getChildAt(0).getLayoutParams(); 31849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!lp.preventEdgeOffset) expandCount -= 0.5f; 31920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 32020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if ((smallestItemsAt & (1 << (childCount - 1))) != 0) { 32120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams lp = ((LayoutParams) getChildAt(childCount - 1).getLayoutParams()); 32249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!lp.preventEdgeOffset) expandCount -= 0.5f; 32320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 32420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 32520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 32620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int extraPixels = expandCount > 0 ? 32720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns (int) (cellsRemaining * cellSize / expandCount) : 0; 32820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 32920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 33049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if ((smallestItemsAt & (1 << i)) == 0) continue; 33120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 33220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 33320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 33420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (child instanceof ActionMenuItemView) { 33520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // If this is one of our views, expand and measure at the larger size. 33620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.extraPixels = extraPixels; 33720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expanded = true; 33820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (i == 0 && !lp.preventEdgeOffset) { 33920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // First item gets part of its new padding pushed out of sight. 34020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // The last item will get this implicitly from layout. 34120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.leftMargin = -extraPixels / 2; 34220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 34320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns needsExpansion = true; 34420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } else if (lp.isOverflowButton) { 34520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.extraPixels = extraPixels; 34620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expanded = true; 34720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.rightMargin = -extraPixels / 2; 34820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns needsExpansion = true; 34920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } else { 35020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // If we don't know what it is, give it some margins instead 35120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // and let it center within its space. We still want to pin 35220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // against the edges. 35320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (i != 0) { 35420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.leftMargin = extraPixels / 2; 35520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 35620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (i != childCount - 1) { 35720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.rightMargin = extraPixels / 2; 35820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 35920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 36020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 36120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 36220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns cellsRemaining = 0; 36320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 364bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 36520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Remeasure any items that have had extra space allocated to them. 36620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (needsExpansion) { 36720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 36820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(i); 36920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 370bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 37149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!lp.expanded) continue; 372bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 37320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int width = lp.cellsUsed * cellSize + lp.extraPixels; 37420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), 37520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns itemHeightSpec); 37620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 377bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 378bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 37920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (heightMode != MeasureSpec.EXACTLY) { 38020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns heightSize = maxChildHeight; 381bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 382bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 38320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns setMeasuredDimension(widthSize, heightSize); 384bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 385bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 38620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns /** 38749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Measure a child view to fit within cell-based formatting. The child's width 38849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * will be measured to a whole multiple of cellSize. 38920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * 39020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * <p>Sets the expandable and cellsUsed fields of LayoutParams. 39120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * 39249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param child Child to measure 39349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param cellSize Size of one cell 39449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param cellsRemaining Number of cells remaining that this view can expand to fill 39520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * @param parentHeightMeasureSpec MeasureSpec used by the parent view 39649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param parentHeightPadding Padding present in the parent view 39720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns * @return Number of cells this child was measured to occupy 39820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns */ 39920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns static int measureChildForCells(View child, int cellSize, int cellsRemaining, 40020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int parentHeightMeasureSpec, int parentHeightPadding) { 401bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell final LayoutParams lp = (LayoutParams) child.getLayoutParams(); 402bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 40320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec) - 40420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns parentHeightPadding; 40520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); 40620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childHeightSpec = MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode); 40720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 40820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final ActionMenuItemView itemView = child instanceof ActionMenuItemView ? 40920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns (ActionMenuItemView) child : null; 41020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean hasText = itemView != null && itemView.hasText(); 41120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 41220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int cellsUsed = 0; 41320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (cellsRemaining > 0 && (!hasText || cellsRemaining >= 2)) { 41420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childWidthSpec = MeasureSpec.makeMeasureSpec( 41520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns cellSize * cellsRemaining, MeasureSpec.AT_MOST); 41620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns child.measure(childWidthSpec, childHeightSpec); 41720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 41820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int measuredWidth = child.getMeasuredWidth(); 41920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns cellsUsed = measuredWidth / cellSize; 42049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (measuredWidth % cellSize != 0) cellsUsed++; 42149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (hasText && cellsUsed < 2) cellsUsed = 2; 42220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 423bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 42420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final boolean expandable = !lp.isOverflowButton && hasText; 42520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.expandable = expandable; 426bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 42720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns lp.cellsUsed = cellsUsed; 42820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int targetWidth = cellsUsed * cellSize; 42920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns child.measure(MeasureSpec.makeMeasureSpec(targetWidth, MeasureSpec.EXACTLY), 43020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns childHeightSpec); 43120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return cellsUsed; 432bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 433bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 43420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 43520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 43620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (!mFormatItems) { 43720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super.onLayout(changed, left, top, right, bottom); 43820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return; 43920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 440bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 44120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int childCount = getChildCount(); 4422f4abc2b347f34ba070a2a5e87cf16ee2c373192Chris Banes final int midVertical = (bottom - top) / 2; 44349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int dividerWidth = getDividerWidth(); 44420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int overflowWidth = 0; 44520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int nonOverflowWidth = 0; 44620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int nonOverflowCount = 0; 44720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int widthRemaining = right - left - getPaddingRight() - getPaddingLeft(); 44820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns boolean hasOverflow = false; 449a2c72b87007d10202c25e78e904938f770c6337dChris Banes final boolean isLayoutRtl = ViewUtils.isLayoutRtl(this); 45020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns for (int i = 0; i < childCount; i++) { 45120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View v = getChildAt(i); 45220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (v.getVisibility() == GONE) { 45320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns continue; 45420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 45520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 45620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams p = (LayoutParams) v.getLayoutParams(); 45720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (p.isOverflowButton) { 45820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns overflowWidth = v.getMeasuredWidth(); 4591582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes if (hasSupportDividerBeforeChildAt(i)) { 4601582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes overflowWidth += dividerWidth; 4611582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes } 46220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int height = v.getMeasuredHeight(); 463a2c72b87007d10202c25e78e904938f770c6337dChris Banes int r; 464a2c72b87007d10202c25e78e904938f770c6337dChris Banes int l; 465a2c72b87007d10202c25e78e904938f770c6337dChris Banes if (isLayoutRtl) { 466a2c72b87007d10202c25e78e904938f770c6337dChris Banes l = getPaddingLeft() + p.leftMargin; 467a2c72b87007d10202c25e78e904938f770c6337dChris Banes r = l + overflowWidth; 468a2c72b87007d10202c25e78e904938f770c6337dChris Banes } else { 469a2c72b87007d10202c25e78e904938f770c6337dChris Banes r = getWidth() - getPaddingRight() - p.rightMargin; 470a2c72b87007d10202c25e78e904938f770c6337dChris Banes l = r - overflowWidth; 471a2c72b87007d10202c25e78e904938f770c6337dChris Banes } 47220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int t = midVertical - (height / 2); 47320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns int b = t + height; 47420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns v.layout(l, t, r, b); 47520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 47620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns widthRemaining -= overflowWidth; 47720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns hasOverflow = true; 47820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } else { 47920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int size = v.getMeasuredWidth() + p.leftMargin + p.rightMargin; 48020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns nonOverflowWidth += size; 48120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns widthRemaining -= size; 4821582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes if (hasSupportDividerBeforeChildAt(i)) { 4831582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes nonOverflowWidth += dividerWidth; 4841582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes } 48520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns nonOverflowCount++; 48620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 48720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 48820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 48920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (childCount == 1 && !hasOverflow) { 49020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns // Center a single child 49120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View v = getChildAt(0); 49220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int width = v.getMeasuredWidth(); 49320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int height = v.getMeasuredHeight(); 49420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int midHorizontal = (right - left) / 2; 49520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int l = midHorizontal - width / 2; 49620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int t = midVertical - height / 2; 49720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns v.layout(l, t, l + width, t + height); 49820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return; 49920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 50020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 50120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int spacerCount = nonOverflowCount - (hasOverflow ? 0 : 1); 50220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final int spacerSize = Math.max(0, spacerCount > 0 ? widthRemaining / spacerCount : 0); 50320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 504a2c72b87007d10202c25e78e904938f770c6337dChris Banes if (isLayoutRtl) { 505a2c72b87007d10202c25e78e904938f770c6337dChris Banes int startRight = getWidth() - getPaddingRight(); 506a2c72b87007d10202c25e78e904938f770c6337dChris Banes for (int i = 0; i < childCount; i++) { 507a2c72b87007d10202c25e78e904938f770c6337dChris Banes final View v = getChildAt(i); 508a2c72b87007d10202c25e78e904938f770c6337dChris Banes final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 509a2c72b87007d10202c25e78e904938f770c6337dChris Banes if (v.getVisibility() == GONE || lp.isOverflowButton) { 510a2c72b87007d10202c25e78e904938f770c6337dChris Banes continue; 511a2c72b87007d10202c25e78e904938f770c6337dChris Banes } 512a2c72b87007d10202c25e78e904938f770c6337dChris Banes 513a2c72b87007d10202c25e78e904938f770c6337dChris Banes startRight -= lp.rightMargin; 514a2c72b87007d10202c25e78e904938f770c6337dChris Banes int width = v.getMeasuredWidth(); 515a2c72b87007d10202c25e78e904938f770c6337dChris Banes int height = v.getMeasuredHeight(); 516a2c72b87007d10202c25e78e904938f770c6337dChris Banes int t = midVertical - height / 2; 517a2c72b87007d10202c25e78e904938f770c6337dChris Banes v.layout(startRight - width, t, startRight, t + height); 518a2c72b87007d10202c25e78e904938f770c6337dChris Banes startRight -= width + lp.leftMargin + spacerSize; 51920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 520a2c72b87007d10202c25e78e904938f770c6337dChris Banes } else { 521a2c72b87007d10202c25e78e904938f770c6337dChris Banes int startLeft = getPaddingLeft(); 522a2c72b87007d10202c25e78e904938f770c6337dChris Banes for (int i = 0; i < childCount; i++) { 523a2c72b87007d10202c25e78e904938f770c6337dChris Banes final View v = getChildAt(i); 524a2c72b87007d10202c25e78e904938f770c6337dChris Banes final LayoutParams lp = (LayoutParams) v.getLayoutParams(); 525a2c72b87007d10202c25e78e904938f770c6337dChris Banes if (v.getVisibility() == GONE || lp.isOverflowButton) { 526a2c72b87007d10202c25e78e904938f770c6337dChris Banes continue; 527a2c72b87007d10202c25e78e904938f770c6337dChris Banes } 52820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 529a2c72b87007d10202c25e78e904938f770c6337dChris Banes startLeft += lp.leftMargin; 530a2c72b87007d10202c25e78e904938f770c6337dChris Banes int width = v.getMeasuredWidth(); 531a2c72b87007d10202c25e78e904938f770c6337dChris Banes int height = v.getMeasuredHeight(); 532a2c72b87007d10202c25e78e904938f770c6337dChris Banes int t = midVertical - height / 2; 533a2c72b87007d10202c25e78e904938f770c6337dChris Banes v.layout(startLeft, t, startLeft + width, t + height); 534a2c72b87007d10202c25e78e904938f770c6337dChris Banes startLeft += width + lp.rightMargin + spacerSize; 535a2c72b87007d10202c25e78e904938f770c6337dChris Banes } 53620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 53720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 53820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 53920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 54020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public void onDetachedFromWindow() { 54120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super.onDetachedFromWindow(); 54249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes dismissPopupMenus(); 54320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 54420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 54549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 54620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean isOverflowReserved() { 54720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return mReserveOverflow; 54820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 54920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 55049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 55120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public void setOverflowReserved(boolean reserveOverflow) { 55220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mReserveOverflow = reserveOverflow; 55320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 55420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 55520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 55620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns protected LayoutParams generateDefaultLayoutParams() { 55720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, 55820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams.WRAP_CONTENT); 55920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns params.gravity = Gravity.CENTER_VERTICAL; 56020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return params; 561bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 562bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 56320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 56420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public LayoutParams generateLayoutParams(AttributeSet attrs) { 56520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return new LayoutParams(getContext(), attrs); 566bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 567bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 56820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 56920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 57049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (p != null) { 57149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final LayoutParams result = p instanceof LayoutParams 57249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes ? new LayoutParams((LayoutParams) p) 57349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes : new LayoutParams(p); 57420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (result.gravity <= Gravity.NO_GRAVITY) { 57520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns result.gravity = Gravity.CENTER_VERTICAL; 57620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 57720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return result; 57820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 57920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return generateDefaultLayoutParams(); 580bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 58120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 58220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @Override 58320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 58420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return p != null && p instanceof LayoutParams; 585bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 58620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 58749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 58820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public LayoutParams generateOverflowButtonLayoutParams() { 58920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns LayoutParams result = generateDefaultLayoutParams(); 59020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns result.isOverflowButton = true; 59120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return result; 592bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 59320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 59449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 59520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean invokeItem(MenuItemImpl item) { 59620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return mMenu.performItemAction(item, 0); 597bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 59820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 59949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 60020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public int getWindowAnimations() { 60120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return 0; 60220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 60320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 60449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 60520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public void initialize(MenuBuilder menu) { 60620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mMenu = menu; 60720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 60820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 60949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 61049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns the Menu object that this ActionMenuView is currently presenting. 61149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 61249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * <p>Applications should use this method to obtain the ActionMenuView's Menu object 61349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * and inflate or add content to it as necessary.</p> 61449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 61549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return the Menu presented by this view 61649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 61749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public Menu getMenu() { 61849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mMenu == null) { 61949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final Context context = getContext(); 62049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMenu = new MenuBuilder(context); 62149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMenu.setCallback(new MenuBuilderCallback()); 62249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter = new ActionMenuPresenter(context); 623ae5248b8902c62325fafbdac3fe18783aec06073Chris Banes mPresenter.setReserveOverflow(true); 624c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes mPresenter.setCallback(mActionMenuPresenterCallback != null 625c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes ? mActionMenuPresenterCallback : new ActionMenuPresenterCallback()); 62649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mMenu.addMenuPresenter(mPresenter, mPopupContext); 62749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter.setMenuView(this); 62849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 62949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 63049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mMenu; 63149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 63249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 63349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 634c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes * Must be called before the first call to getMenu() 635c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes * @hide 636c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes */ 637c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes public void setMenuCallbacks(MenuPresenter.Callback pcb, MenuBuilder.Callback mcb) { 638c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes mActionMenuPresenterCallback = pcb; 639c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes mMenuBuilderCallback = mcb; 640c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 641c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes 642c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes /** 64349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Returns the current menu or null if one has not yet been configured. 64449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @hide Internal use only for action bar integration 64549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 64649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public MenuBuilder peekMenu() { 64749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mMenu; 64849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 64949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 65049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 65149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Show the overflow items from the associated menu. 65249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 65349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if the menu was able to be shown, false otherwise 65449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 65549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean showOverflowMenu() { 65649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPresenter != null && mPresenter.showOverflowMenu(); 65749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 65849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 65949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 66049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Hide the overflow items from the associated menu. 66149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 66249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if the menu was able to be hidden, false otherwise 66349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 66449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean hideOverflowMenu() { 66549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPresenter != null && mPresenter.hideOverflowMenu(); 66649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 66749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 66849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 66949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Check whether the overflow menu is currently showing. This may not reflect 67049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * a pending show operation in progress. 67149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 67249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return true if the overflow menu is currently showing 67349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 67449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean isOverflowMenuShowing() { 67549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPresenter != null && mPresenter.isOverflowMenuShowing(); 67649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 67749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 67849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 67949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean isOverflowMenuShowPending() { 68049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPresenter != null && mPresenter.isOverflowMenuShowPending(); 68149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 68249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 68349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 68449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Dismiss any popups associated with this menu view. 68549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 68649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void dismissPopupMenus() { 68749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (mPresenter != null) { 68849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter.dismissPopupMenus(); 68949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 69049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 69149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 692a2c72b87007d10202c25e78e904938f770c6337dChris Banes /** 693a2c72b87007d10202c25e78e904938f770c6337dChris Banes * @hide Private LinearLayout (superclass) API. Un-hide if LinearLayout API is made public. 694a2c72b87007d10202c25e78e904938f770c6337dChris Banes */ 6951582fcfe4f727e3547ed17a2df3067234c9a4141Chris Banes protected boolean hasSupportDividerBeforeChildAt(int childIndex) { 69649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (childIndex == 0) { 69749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 69849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 69920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View childBefore = getChildAt(childIndex - 1); 70020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns final View child = getChildAt(childIndex); 70120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns boolean result = false; 70220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (childIndex < getChildCount() && childBefore instanceof ActionMenuChildView) { 70320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns result |= ((ActionMenuChildView) childBefore).needsDividerAfter(); 70420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 70520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (childIndex > 0 && child instanceof ActionMenuChildView) { 70620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns result |= ((ActionMenuChildView) child).needsDividerBefore(); 70720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 70820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return result; 709bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 710bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 71120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { 71220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return false; 713bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 714bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 71549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 71649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setExpandedActionViewsExclusive(boolean exclusive) { 71749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPresenter.setExpandedActionViewsExclusive(exclusive); 71849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 71920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 72049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 72149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * Interface responsible for receiving menu item click events if the items themselves 72249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * do not have individual item click listeners. 72349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 72449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public interface OnMenuItemClickListener { 72549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** 72649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * This method will be invoked when a menu item is clicked if the item itself did 72749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * not already handle the event. 72849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * 72949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @param item {@link MenuItem} that was clicked 73049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes * @return <code>true</code> if the event was handled, <code>false</code> otherwise. 73149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes */ 73249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean onMenuItemClick(MenuItem item); 73349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 73420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 73549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private class MenuBuilderCallback implements MenuBuilder.Callback { 73649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 73749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 73849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mOnMenuItemClickListener != null && 73949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mOnMenuItemClickListener.onMenuItemClick(item); 74049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 74149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 74249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 74349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void onMenuModeChange(MenuBuilder menu) { 744c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes if (mMenuBuilderCallback != null) { 745c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes mMenuBuilderCallback.onMenuModeChange(menu); 746c4b9e0cb716a4caff218b27d86f37ef8117d257bChris Banes } 74749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 74849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 74949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 75049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private class ActionMenuPresenterCallback implements ActionMenuPresenter.Callback { 75149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 75249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 75349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 75449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 75549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes @Override 75649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean onOpenSubMenu(MenuBuilder subMenu) { 75749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return false; 75849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 75949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 76049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 76149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** @hide */ 76249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public interface ActionMenuChildView { 76349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public boolean needsDividerBefore(); 76420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean needsDividerAfter(); 765bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 766bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 76749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public static class LayoutParams extends LinearLayoutCompat.LayoutParams { 76820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 76920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @ViewDebug.ExportedProperty() 77020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean isOverflowButton; 77120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 77220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @ViewDebug.ExportedProperty() 77320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public int cellsUsed; 77420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 77520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @ViewDebug.ExportedProperty() 77620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public int extraPixels; 77720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 77820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @ViewDebug.ExportedProperty() 77920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean expandable; 78020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 78120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns @ViewDebug.ExportedProperty() 78220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public boolean preventEdgeOffset; 78320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 78449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean expanded; 78520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 78620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public LayoutParams(Context c, AttributeSet attrs) { 78720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super(c, attrs); 78820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 78920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 79049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public LayoutParams(ViewGroup.LayoutParams other) { 79149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super(other); 79249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 79349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 79420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public LayoutParams(LayoutParams other) { 79549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes super((ViewGroup.LayoutParams) other); 79620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns isOverflowButton = other.isOverflowButton; 79720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 79820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 79920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns public LayoutParams(int width, int height) { 80020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super(width, height); 80120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns isOverflowButton = false; 80220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 80320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 80449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes LayoutParams(int width, int height, boolean isOverflowButton) { 80520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns super(width, height); 80620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns this.isOverflowButton = isOverflowButton; 80720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 808bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 809bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell} 810