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; 23da10fdd1400ecfd8d7f2e55651dd528d0614dfc5Jeff Brownimport android.support.v7.internal.widget.ListPopupWindow; 24bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.KeyEvent; 25bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.LayoutInflater; 2630837f1095c803f332f4a1c3f0917c8afdd50156Adam Powellimport android.view.MenuItem; 27bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View; 28bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.View.MeasureSpec; 29bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewGroup; 30bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.view.ViewTreeObserver; 31bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.AdapterView; 32bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.BaseAdapter; 33bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.FrameLayout; 34bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.ListAdapter; 35bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport android.widget.PopupWindow; 36bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 37bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellimport java.util.ArrayList; 38bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 39bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell/** 40bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * Presents a menu as a small, simple popup anchored to another view. 41ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani * 42bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell * @hide 43bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell */ 44bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powellpublic class MenuPopupHelper implements AdapterView.OnItemClickListener, View.OnKeyListener, 4520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener, 4620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns MenuPresenter { 4720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 48ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private static final String TAG = "MenuPopupHelper"; 49bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 50ee7c9fb199e9b9af8d40a1f9e27d85465acf8301Chris Banes static final int ITEM_LAYOUT = R.layout.abc_popup_menu_item_layout; 51bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 52ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private Context mContext; 53ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private LayoutInflater mInflater; 54ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private ListPopupWindow mPopup; 55ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuBuilder mMenu; 56ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mPopupMaxWidth; 57ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private View mAnchorView; 58ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private boolean mOverflowOnly; 59ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private ViewTreeObserver mTreeObserver; 60bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 61ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuAdapter mAdapter; 62bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 63ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private Callback mPresenterCallback; 64bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 65ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean mForceShowIcon; 66bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 67ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private ViewGroup mMeasureParent; 68bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 69ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuPopupHelper(Context context, MenuBuilder menu) { 70ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani this(context, menu, null, false); 71ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 72bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 73ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuPopupHelper(Context context, MenuBuilder menu, View anchorView) { 74ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani this(context, menu, anchorView, false); 75ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 76bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 77ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuPopupHelper(Context context, MenuBuilder menu, 7820ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns View anchorView, boolean overflowOnly) { 79ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mContext = context; 80ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mInflater = LayoutInflater.from(context); 81ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMenu = menu; 82ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mOverflowOnly = overflowOnly; 83bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 84ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final Resources res = context.getResources(); 85ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopupMaxWidth = Math.max(res.getDisplayMetrics().widthPixels / 2, 8607a07ce59efb770e9fb9ca53a0133e5e64a63bbcChris Banes res.getDimensionPixelSize(R.dimen.abc_config_prefDialogWidth)); 87bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 88ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAnchorView = anchorView; 89bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 90ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani menu.addMenuPresenter(this); 91ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 92bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 93ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setAnchorView(View anchor) { 94ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAnchorView = anchor; 95ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 96bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 97ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setForceShowIcon(boolean forceShow) { 98ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mForceShowIcon = forceShow; 99bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 100ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 101ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void show() { 102ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (!tryShow()) { 103ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new IllegalStateException("MenuPopupHelper cannot be used without an anchor"); 104ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 105bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 106bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 107ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean tryShow() { 108ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup = new ListPopupWindow(mContext, null, R.attr.popupMenuStyle); 109ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnDismissListener(this); 110ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setOnItemClickListener(this); 111ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 112ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAdapter = new MenuAdapter(mMenu); 113ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAdapter(mAdapter); 114ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setModal(true); 115ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 116ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View anchor = mAnchorView; 117ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor != null) { 118ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final boolean addGlobalListener = mTreeObserver == null; 119ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest 12020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (addGlobalListener) { 12120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mTreeObserver.addOnGlobalLayoutListener(this); 12220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 123ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setAnchorView(anchor); 124ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else { 125ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 126ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 127bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 128ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setContentWidth(Math.min(measureContentWidth(mAdapter), mPopupMaxWidth)); 129ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED); 130ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 131ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.getListView().setOnKeyListener(this); 132ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 133bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 134ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 135ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void dismiss() { 136ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 137ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.dismiss(); 138ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 139bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 140ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 141ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onDismiss() { 142ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup = null; 143ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMenu.close(); 144ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mTreeObserver != null) { 14520ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (!mTreeObserver.isAlive()) { 14620ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mTreeObserver = mAnchorView.getViewTreeObserver(); 14720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 148ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver.removeGlobalOnLayoutListener(this); 149ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mTreeObserver = null; 150ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 151bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 152ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 153ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean isShowing() { 154ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return mPopup != null && mPopup.isShowing(); 155bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 156bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 157ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 158ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 159ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuAdapter adapter = mAdapter; 160ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani adapter.mAdapterMenu.performItemAction(adapter.getItem(position), 0); 161ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 162bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 163ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onKey(View v, int keyCode, KeyEvent event) { 164ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_MENU) { 165ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 166ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 167ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 168ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 169bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 170ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 171ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int measureContentWidth(ListAdapter adapter) { 172ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Menus don't tend to be long, so this is more sane than it looks. 173ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani int width = 0; 174ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani View itemView = null; 175ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani int itemType = 0; 176ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int widthMeasureSpec = 17720ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 178ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int heightMeasureSpec = 17920ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 180ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = adapter.getCount(); 181ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 182ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int positionType = adapter.getItemViewType(i); 183ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (positionType != itemType) { 184ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemType = positionType; 185ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = null; 186ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 187ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mMeasureParent == null) { 188ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mMeasureParent = new FrameLayout(mContext); 189ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 190ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView = adapter.getView(i, itemView, mMeasureParent); 191ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.measure(widthMeasureSpec, heightMeasureSpec); 192ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani width = Math.max(width, itemView.getMeasuredWidth()); 193bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 194ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return width; 195ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 196bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 197ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 198ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onGlobalLayout() { 199ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (isShowing()) { 200ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final View anchor = mAnchorView; 201ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (anchor == null || !anchor.isShown()) { 202ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 203ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } else if (isShowing()) { 204ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Recompute window size and position 205ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPopup.show(); 206ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 207bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 208bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 209bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 210ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 211ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void initForMenu(Context context, MenuBuilder menu) { 212ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Don't need to do anything; we added as a presenter in the constructor. 213bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 214bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 215ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 216ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuView getMenuView(ViewGroup root) { 217ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani throw new UnsupportedOperationException("MenuPopupHelpers manage their own views"); 218bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 219bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 220ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 221ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void updateMenuView(boolean cleared) { 22220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (mAdapter != null) { 22320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapter.notifyDataSetChanged(); 22420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 225bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 226bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 227ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 228ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void setCallback(Callback cb) { 229ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback = cb; 230bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 231bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 232ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 233ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean onSubMenuSelected(SubMenuBuilder subMenu) { 234ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subMenu.hasVisibleItems()) { 235ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuPopupHelper subPopup = new MenuPopupHelper(mContext, subMenu, mAnchorView, false); 236ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setCallback(mPresenterCallback); 237ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 238ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani boolean preserveIconSpacing = false; 239ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = subMenu.size(); 240ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 241ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuItem childItem = subMenu.getItem(i); 242ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (childItem.isVisible() && childItem.getIcon() != null) { 243ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani preserveIconSpacing = true; 244ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani break; 245ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 246ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 247ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani subPopup.setForceShowIcon(preserveIconSpacing); 248ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 249ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (subPopup.tryShow()) { 250ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 251ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onOpenSubMenu(subMenu); 252ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 253ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return true; 254ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 255ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 256ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 257bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 258bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 259ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 260ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 261ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Only care about the (sub)menu we're presenting. 26220ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns if (menu != mMenu) { 26320ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns return; 26420ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns } 265ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 266ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani dismiss(); 267ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mPresenterCallback != null) { 268ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); 269bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 270bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 271bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell 272bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell @Override 273ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean flagActionItems() { 274ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 275ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 276ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 277ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 278ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 279ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 280ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 281ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 282ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return false; 283ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 284ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 285ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 286ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getId() { 287ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return 0; 288ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 289ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 290ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 291ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public Parcelable onSaveInstanceState() { 292ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return null; 293ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 294ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 295ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 296ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void onRestoreInstanceState(Parcelable state) { 297ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 298ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 299ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private class MenuAdapter extends BaseAdapter { 30020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns 301ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private MenuBuilder mAdapterMenu; 302ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani private int mExpandedIndex = -1; 303ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 304ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuAdapter(MenuBuilder menu) { 305ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mAdapterMenu = menu; 306ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 307ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 308ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 309ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public int getCount() { 310ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 31120ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 312ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex < 0) { 313ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size(); 314ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 315ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.size() - 1; 316ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 317ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 318ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public MenuItemImpl getItem(int position) { 319ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ArrayList<MenuItemImpl> items = mOverflowOnly ? 32020ac724a3a836bfd362c911f7dc55a61c02b4d44Trevor Johns mAdapterMenu.getNonActionItems() : mAdapterMenu.getVisibleItems(); 321ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mExpandedIndex >= 0 && position >= mExpandedIndex) { 322ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani position++; 323ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 324ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return items.get(position); 325ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 326ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 327ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public long getItemId(int position) { 328ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // Since a menu item's ID is optional, we'll use the position as an 329ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani // ID for the item in the AdapterView 330ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return position; 331ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 332ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 333ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public View getView(int position, View convertView, ViewGroup parent) { 334ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (convertView == null) { 335ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani convertView = mInflater.inflate(ITEM_LAYOUT, parent, false); 336ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 337ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 338ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani MenuView.ItemView itemView = (MenuView.ItemView) convertView; 339ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (mForceShowIcon) { 340ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani ((ListMenuItemView) convertView).setForceShowIcon(true); 341ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 342ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani itemView.initialize(getItem(position), 0); 343ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return convertView; 344ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 345ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 346ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani void findExpandedIndex() { 347ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl expandedItem = mMenu.getExpandedItem(); 348ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (expandedItem != null) { 349ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems(); 350ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final int count = items.size(); 351ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani for (int i = 0; i < count; i++) { 352ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani final MenuItemImpl item = items.get(i); 353ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani if (item == expandedItem) { 354ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = i; 355ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani return; 356ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 357ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 358ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 359ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani mExpandedIndex = -1; 360ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 361ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 362ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani @Override 363ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani public void notifyDataSetChanged() { 364ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani findExpandedIndex(); 365ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani super.notifyDataSetChanged(); 366ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani } 367bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell } 368bbbb8f39d1b1d1b317c5f9237f20fe6b1d9eb17fAdam Powell} 369ced50ab7536cd3d3573f03310fc899f10c414d37Anirudh Dewani 370