MenuPopupHelper.java revision a9cf27da7f78d81db5ad482003a10d1a6562107c
1bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/* 2bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Copyright (C) 2010 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 */ 16bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 17da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownpackage android.support.v7.internal.view.menu; 18bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 19bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.Context; 20bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.content.res.Resources; 21bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.os.Parcelable; 22da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.appcompat.R; 2349c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.support.v7.widget.ListPopupWindow; 2449c78900da0d43140fb602431fb93212bd7f6c70Chris Banesimport android.view.Gravity; 25bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent; 26bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.LayoutInflater; 2730837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem; 28bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View; 29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View.MeasureSpec; 30bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup; 31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewTreeObserver; 32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.AdapterView; 33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.BaseAdapter; 34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.FrameLayout; 35bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.ListAdapter; 36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.PopupWindow; 37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList; 39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 40bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/** 41bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Presents a menu as a small, simple popup anchored to another view. 42ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * 43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide 44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 45bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellpublic class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener, 4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener, 4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns MenuPresenter { 4820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 49ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private static final String TAG = "MenuPopupHelper"; 50bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 51ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes static final int ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout; 52bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 5349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final Context mContext; 5449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final LayoutInflater mInflater; 5549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final MenuBuilder mMenu; 5649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final MenuAdapter mAdapter; 5749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final boolean mOverflowOnly; 5849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final int mPopupMaxWidth; 5949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private final int mPopupStyleAttr; 60a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette private final int mPopupStyleRes; 6149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 62ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private View mAnchorView; 6349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private ListPopupWindow mPopup; 64ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private ViewTreeObserver mTreeObserver; 65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private Callback mPresenterCallback; 66bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean mForceShowIcon; 68bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private ViewGroup mMeasureParent; 70bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 7149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** Whether the cached content width value is valid. */ 7249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private boolean mHasContentWidth; 7349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 7449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes /** Cached content width from {@link #measureContentWidth}. */ 7549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mContentWidth; 7649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 7749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int mDropDownGravity = Gravity.NO_GRAVITY; 7849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuPopupHelper(Context context, MenuBuilder menu) { 8049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this(context, menu, null, false, R.attr.popupMenuStyle); 81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 82bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 83ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { 8449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes this(context, menu, anchorView, false, R.attr.popupMenuStyle); 85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 86bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 8749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, 8849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes boolean overflowOnly, int popupStyleAttr) { 89a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette this(context, menu, anchorView, overflowOnly, popupStyleAttr, 0); 90a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette } 91a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette 92a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView, 93a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette boolean overflowOnly, int popupStyleAttr, int popupStyleRes) { 94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mContext = context; 95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mInflater = LayoutInflater.from(context); 96ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMenu = menu; 9749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mAdapter = new MenuAdapter(mMenu); 98ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mOverflowOnly = overflowOnly; 9949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopupStyleAttr = popupStyleAttr; 100a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette mPopupStyleRes = popupStyleRes; 101bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final Resources res = context.getResources(); 103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, 10407a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes res.getDimensionPixelSize(R.dimen.abc_config_prefDialogWidth)); 105bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 106ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAnchorView = anchorView; 107bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 10849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes // Present the menu using our context, not the menu builder's context. 10949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes menu.addMenuPresenter(this, context); 110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 111bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setAnchorView(View anchor) { 113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAnchorView = anchor; 114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 115bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setForceShowIcon(boolean forceShow) { 117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mForceShowIcon = forceShow; 118bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 12049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public void setGravity(int gravity) { 12149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mDropDownGravity = gravity; 12249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 12349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void show() { 125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (!tryShow()) { 126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); 127ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 128bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 129bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 13049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public ListPopupWindow getPopup() { 13149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopup; 13249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 13349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean tryShow() { 135a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr, mPopupStyleRes); 136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnDismissListener(this); 137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnItemClickListener(this); 138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAdapter(mAdapter); 139ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setModal(true); 140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View anchor = mAnchorView; 142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor != null) { 143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final boolean addGlobalListener = mTreeObserver == null; 144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest 14549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this); 146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAnchorView(anchor); 14749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopup.setDropDownGravity(mDropDownGravity); 148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else { 149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 151bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 15249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!mHasContentWidth) { 15349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mContentWidth = measureContentWidth(); 15449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mHasContentWidth = true; 15549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 15649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopup.setContentWidth(mContentWidth); 158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); 159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.getListView().setOnKeyListener(this); 161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 162bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void dismiss() { 165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.dismiss(); 167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 168bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onDismiss() { 171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup = null; 172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMenu.close(); 173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mTreeObserver != null) { 17449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver(); 175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver.removeGlobalOnLayoutListener(this); 176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = null; 177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 178bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean isShowing() { 181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return mPopup != null && mPopup.isShowing(); 182bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 183bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuAdapter adapter = mAdapter; 187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); 188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 189bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onKey(View v, int keyCode, KeyEvent event) { 191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { 192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 193ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 196bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 19849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int measureContentWidth() { 199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Menus don't tend to be long, so this is more sane than it looks. 20049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int maxWidth = 0; 201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View itemView = null; 202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani int itemType = 0; 20349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 20449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final ListAdapter adapter = mAdapter; 20549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 20649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 207ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = adapter.getCount(); 208ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 209ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int positionType = adapter.getItemViewType(i); 210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (positionType != itemType) { 211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemType = positionType; 212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = null; 213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 21449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mMeasureParent == null) { 216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMeasureParent = new FrameLayout(mContext); 217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = adapter.getView(i, itemView, mMeasureParent); 220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.measure(widthMeasureSpec, heightMeasureSpec); 22149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 22249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int itemWidth = itemView.getMeasuredWidth(); 22349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (itemWidth >= mPopupMaxWidth) { 22449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopupMaxWidth; 22549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (itemWidth > maxWidth) { 22649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = itemWidth; 22749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 228bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 23049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return maxWidth; 231ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 232bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onGlobalLayout() { 235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final View anchor = mAnchorView; 237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor == null || !anchor.isShown()) { 238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else if (isShowing()) { 240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Recompute window size and position 241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 243bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 244bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 245bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void initForMenu(Context context, MenuBuilder menu) { 248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Don't need to do anything; we added as a presenter in the constructor. 249bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 250bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuView getMenuView(ViewGroup root) { 253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new UnsupportedOperationException("MenuPopupHelpers manage their own views"); 254bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 255bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void updateMenuView(boolean cleared) { 25849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mHasContentWidth = false; 25949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 26020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (mAdapter != null) { 26120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapter.notifyDataSetChanged(); 26220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 263bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 264bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setCallback(Callback cb) { 267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback = cb; 268bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 269bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 272ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subMenu.hasVisibleItems()) { 27349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView); 274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setCallback(mPresenterCallback); 275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean preserveIconSpacing = false; 277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = subMenu.size(); 278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuItem childItem = subMenu.getItem(i); 280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (childItem.isVisible() && childItem.getIcon() != null) { 281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani preserveIconSpacing = true; 282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani break; 283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setForceShowIcon(preserveIconSpacing); 286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subPopup.tryShow()) { 288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onOpenSubMenu(subMenu); 290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 295bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 296bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Only care about the (sub)menu we're presenting. 30049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (menu != mMenu) return; 301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 305bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 306bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 307bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 308bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell @Override 309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean flagActionItems() { 310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 311ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getId() { 323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return 0; 324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public Parcelable onSaveInstanceState() { 328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return null; 329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onRestoreInstanceState(Parcelable state) { 333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private class MenuAdapter extends BaseAdapter { 336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuBuilder mAdapterMenu; 337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mExpandedIndex = -1; 338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuAdapter(MenuBuilder menu) { 340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAdapterMenu = menu; 341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getCount() { 345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 34620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex < 0) { 348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size(); 349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size() - 1; 351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuItemImpl getItem(int position) { 354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 35520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex >= 0 && position >= mExpandedIndex) { 357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani position++; 358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.get(position); 360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public long getItemId(int position) { 363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Since a menu item's ID is optional, we'll use the position as an 364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // ID for the item in the AdapterView 365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return position; 366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public View getView(int position, View convertView, ViewGroup parent) { 369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (convertView == null) { 370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); 371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuView.ItemView itemView = (MenuView.ItemView) convertView; 374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mForceShowIcon) { 375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ((ListMenuItemView) convertView).setForceShowIcon(true); 376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.initialize(getItem(position), 0); 378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return convertView; 379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani void findExpandedIndex() { 382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl expandedItem = mMenu.getExpandedItem(); 383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (expandedItem != null) { 384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); 385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = items.size(); 386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl item = items.get(i); 388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (item == expandedItem) { 389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = i; 390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return; 391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = -1; 395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void notifyDataSetChanged() { 399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.notifyDataSetChanged(); 401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 402bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 403bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell} 404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 405