MenuPopupHelper.java revision 66698bb15ba0f873aa1c2290cc50d6bb839a474a
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 1766698bb15ba0f873aa1c2290cc50d6bb839a474aChris Banespackage android.support.v7.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 12444918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes public int getGravity() { 12544918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes return mDropDownGravity; 12644918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes } 12744918a92e1d66a01a03063e2c5e68b2570f64b03Chris Banes 128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void show() { 129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (!tryShow()) { 130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); 131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 132bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 133bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 13449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes public ListPopupWindow getPopup() { 13549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopup; 13649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 13749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean tryShow() { 139a9cf27da7f78d81db5ad482003a10d1a6562107cAlan Viverette mPopup = new ListPopupWindow(mContext, null, mPopupStyleAttr, mPopupStyleRes); 140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnDismissListener(this); 141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnItemClickListener(this); 142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAdapter(mAdapter); 143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setModal(true); 144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 145ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View anchor = mAnchorView; 146ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor != null) { 147ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final boolean addGlobalListener = mTreeObserver == null; 148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest 14949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this); 150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAnchorView(anchor); 15149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopup.setDropDownGravity(mDropDownGravity); 152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else { 153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 155bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 15649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!mHasContentWidth) { 15749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mContentWidth = measureContentWidth(); 15849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mHasContentWidth = true; 15949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 16049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 16149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mPopup.setContentWidth(mContentWidth); 162ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); 163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.getListView().setOnKeyListener(this); 165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 166bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void dismiss() { 169ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.dismiss(); 171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 172bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onDismiss() { 175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup = null; 176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMenu.close(); 177ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mTreeObserver != null) { 17849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (!mTreeObserver.isAlive()) mTreeObserver = mAnchorView.getViewTreeObserver(); 179ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver.removeGlobalOnLayoutListener(this); 180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = null; 181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 182bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean isShowing() { 185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return mPopup != null && mPopup.isShowing(); 186bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 187bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuAdapter adapter = mAdapter; 191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); 192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 193bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onKey(View v, int keyCode, KeyEvent event) { 195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { 196ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 200bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 20249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes private int measureContentWidth() { 203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Menus don't tend to be long, so this is more sane than it looks. 20449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes int maxWidth = 0; 205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View itemView = null; 206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani int itemType = 0; 20749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 20849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final ListAdapter adapter = mAdapter; 20949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 21049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = adapter.getCount(); 212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 213ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int positionType = adapter.getItemViewType(i); 214ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (positionType != itemType) { 215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemType = positionType; 216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = null; 217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 21849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 219ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mMeasureParent == null) { 220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMeasureParent = new FrameLayout(mContext); 221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 22249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 223ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = adapter.getView(i, itemView, mMeasureParent); 224ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.measure(widthMeasureSpec, heightMeasureSpec); 22549c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 22649c78900da0d43140fb602431fb93212bd7f6c70Chris Banes final int itemWidth = itemView.getMeasuredWidth(); 22749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (itemWidth >= mPopupMaxWidth) { 22849c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return mPopupMaxWidth; 22949c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } else if (itemWidth > maxWidth) { 23049c78900da0d43140fb602431fb93212bd7f6c70Chris Banes maxWidth = itemWidth; 23149c78900da0d43140fb602431fb93212bd7f6c70Chris Banes } 232bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 23349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 23449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes return maxWidth; 235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 236bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onGlobalLayout() { 239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final View anchor = mAnchorView; 241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor == null || !anchor.isShown()) { 242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else if (isShowing()) { 244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Recompute window size and position 245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 247bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 248bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 249bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void initForMenu(Context context, MenuBuilder menu) { 252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Don't need to do anything; we added as a presenter in the constructor. 253bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 254bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuView getMenuView(ViewGroup root) { 257ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new UnsupportedOperationException("MenuPopupHelpers manage their own views"); 258bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 259bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void updateMenuView(boolean cleared) { 26249c78900da0d43140fb602431fb93212bd7f6c70Chris Banes mHasContentWidth = false; 26349c78900da0d43140fb602431fb93212bd7f6c70Chris Banes 26420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (mAdapter != null) { 26520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapter.notifyDataSetChanged(); 26620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 267bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 268bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 269ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 270ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setCallback(Callback cb) { 271ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback = cb; 272bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 273bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subMenu.hasVisibleItems()) { 27749c78900da0d43140fb602431fb93212bd7f6c70Chris Banes MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView); 278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setCallback(mPresenterCallback); 279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean preserveIconSpacing = false; 281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = subMenu.size(); 282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuItem childItem = subMenu.getItem(i); 284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (childItem.isVisible() && childItem.getIcon() != null) { 285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani preserveIconSpacing = true; 286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani break; 287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setForceShowIcon(preserveIconSpacing); 290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subPopup.tryShow()) { 292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onOpenSubMenu(subMenu); 294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 299bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 300bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Only care about the (sub)menu we're presenting. 30449c78900da0d43140fb602431fb93212bd7f6c70Chris Banes if (menu != mMenu) return; 305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 309bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 310bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 311bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 312bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell @Override 313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean flagActionItems() { 314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 320ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getId() { 327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return 0; 328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public Parcelable onSaveInstanceState() { 332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return null; 333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onRestoreInstanceState(Parcelable state) { 337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private class MenuAdapter extends BaseAdapter { 340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuBuilder mAdapterMenu; 341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mExpandedIndex = -1; 342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuAdapter(MenuBuilder menu) { 344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAdapterMenu = menu; 345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getCount() { 349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 35020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex < 0) { 352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size(); 353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size() - 1; 355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuItemImpl getItem(int position) { 358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 35920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex >= 0 && position >= mExpandedIndex) { 361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani position++; 362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.get(position); 364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public long getItemId(int position) { 367ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Since a menu item's ID is optional, we'll use the position as an 368ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // ID for the item in the AdapterView 369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return position; 370ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 371ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 372ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public View getView(int position, View convertView, ViewGroup parent) { 373ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (convertView == null) { 374ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); 375ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 376ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 377ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuView.ItemView itemView = (MenuView.ItemView) convertView; 378ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mForceShowIcon) { 379ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ((ListMenuItemView) convertView).setForceShowIcon(true); 380ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 381ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.initialize(getItem(position), 0); 382ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return convertView; 383ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 384ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 385ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani void findExpandedIndex() { 386ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl expandedItem = mMenu.getExpandedItem(); 387ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (expandedItem != null) { 388ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); 389ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = items.size(); 390ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 391ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl item = items.get(i); 392ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (item == expandedItem) { 393ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = i; 394ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return; 395ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 396ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 397ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 398ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = -1; 399ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 400ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 401ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 402ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void notifyDataSetChanged() { 403ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 404ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.notifyDataSetChanged(); 405ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 406bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 407bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell} 408ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 409