MenuPopup.java revision 28a8468995c71ba3fbba12557d143e7599db38d8
1b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg/* 2b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Copyright (C) 2015 The Android Open Source Project 3b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 4b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Licensed under the Apache License, Version 2.0 (the "License"); 5b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * you may not use this file except in compliance with the License. 6b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * You may obtain a copy of the License at 7b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 8b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * http://www.apache.org/licenses/LICENSE-2.0 9b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 10b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Unless required by applicable law or agreed to in writing, software 11b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * distributed under the License is distributed on an "AS IS" BASIS, 12b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * See the License for the specific language governing permissions and 14b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * limitations under the License. 15b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg */ 16b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 17b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergpackage com.android.internal.view.menu; 18b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 1928a8468995c71ba3fbba12557d143e7599db38d8Alan Viveretteimport android.annotation.NonNull; 2028a8468995c71ba3fbba12557d143e7599db38d8Alan Viveretteimport android.annotation.Nullable; 21b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.content.Context; 22ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasbergimport android.view.MenuItem; 23b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.view.View; 24b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.view.View.MeasureSpec; 25b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.view.ViewGroup; 26ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasbergimport android.widget.AdapterView; 27b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.widget.FrameLayout; 28ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasbergimport android.widget.HeaderViewListAdapter; 29b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.widget.ListAdapter; 30b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasbergimport android.widget.PopupWindow; 31b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 32b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg/** 33b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Base class for a menu popup abstraction - i.e., some type of menu, housed in a popup window 34b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * environment. 35b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 36b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * @hide 37b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg */ 38ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasbergpublic abstract class MenuPopup implements ShowableListMenu, MenuPresenter, 39ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg AdapterView.OnItemClickListener { 40b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 41b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public abstract void setForceShowIcon(boolean forceShow); 42b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 43b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg /** 448e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg * Adds the given menu to the popup, if it is capable of displaying submenus within itself. 458e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg * If menu is the first menu shown, it won't be displayed until show() is called. 468e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg * If the popup was already showing, adding a submenu via this method will cause that new 478e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg * submenu to be shown immediately (that is, if this MenuPopup implementation is capable of 488e12f8df076d38853e0fedde7ed79e2e8689d59eOren Blasberg * showing its own submenus). 49b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 50b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * @param menu 51b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg */ 52b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public abstract void addMenu(MenuBuilder menu); 53b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 54b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public abstract void setGravity(int dropDownGravity); 55b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 56b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public abstract void setAnchorView(View anchor); 57b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 58ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg public abstract void setHorizontalOffset(int x); 59ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 60ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg public abstract void setVerticalOffset(int y); 61ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 62ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg /** 63ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * Set whether a title entry should be shown in the popup menu (if a title exists for the 64ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * menu). 65ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * 66ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * @param showTitle 67ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg */ 68ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg public abstract void setShowTitle(boolean showTitle); 69ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 70b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg /** 71b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Set a listener to receive a callback when the popup is dismissed. 72b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 73b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * @param listener Listener that will be notified when the popup is dismissed. 74b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg */ 75b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public abstract void setOnDismissListener(PopupWindow.OnDismissListener listener); 76b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 77b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg @Override 7828a8468995c71ba3fbba12557d143e7599db38d8Alan Viverette public void initForMenu(@NonNull Context context, @Nullable MenuBuilder menu) { 79b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg // Don't need to do anything; we added as a presenter in the constructor. 80b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 81b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 82b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg @Override 83b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public MenuView getMenuView(ViewGroup root) { 84b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg throw new UnsupportedOperationException("MenuPopups manage their own views"); 85b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 86b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 87b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg @Override 88b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public boolean expandItemActionView(MenuBuilder menu, MenuItemImpl item) { 89b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg return false; 90b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 91b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 92b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg @Override 93b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public boolean collapseItemActionView(MenuBuilder menu, MenuItemImpl item) { 94b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg return false; 95b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 96b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 97b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg @Override 98b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg public int getId() { 99b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg return 0; 100b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 101b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 102ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg @Override 103ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 104ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg ListAdapter outerAdapter = (ListAdapter) parent.getAdapter(); 105ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg MenuAdapter wrappedAdapter = toMenuAdapter(outerAdapter); 106ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 107ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg // Use the position from the outer adapter so that if a header view was added, we don't get 108ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg // an off-by-1 error in position. 109ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg wrappedAdapter.mAdapterMenu.performItemAction((MenuItem) outerAdapter.getItem(position), 0); 110ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg } 111ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 112b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg /** 113b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * Measures the width of the given menu view. 114b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * 115b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * @param view The view to measure. 116b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg * @return The width. 117b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg */ 118b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg protected static int measureIndividualMenuWidth(ListAdapter adapter, ViewGroup parent, 119b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg Context context, int maxAllowedWidth) { 120b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg // Menus don't tend to be long, so this is more sane than it looks. 121b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg int maxWidth = 0; 122b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg View itemView = null; 123b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg int itemType = 0; 124b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 125b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 126b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 127b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg final int count = adapter.getCount(); 128b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg for (int i = 0; i < count; i++) { 129b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg final int positionType = adapter.getItemViewType(i); 130b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg if (positionType != itemType) { 131b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg itemType = positionType; 132b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg itemView = null; 133b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 134b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 135b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg if (parent == null) { 136b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg parent = new FrameLayout(context); 137b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 138b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 139b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg itemView = adapter.getView(i, itemView, parent); 140b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg itemView.measure(widthMeasureSpec, heightMeasureSpec); 141b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 142b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg final int itemWidth = itemView.getMeasuredWidth(); 143b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg if (itemWidth >= maxAllowedWidth) { 144b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg return maxAllowedWidth; 145b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } else if (itemWidth > maxWidth) { 146b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg maxWidth = itemWidth; 147b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 148b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 149b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg 150b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg return maxWidth; 151b23976efdd6ffe42cb3b8fe6650fc77bd9a161e8Oren Blasberg } 152ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg 153ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg /** 154ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * Converts the given ListAdapter originating from a menu, to a MenuAdapter, accounting for 155ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * the possibility of the parameter adapter actually wrapping the MenuAdapter. (That could 156ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * happen if a header view was added on the menu.) 157ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * 158ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * @param adapter 159ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg * @return 160ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg */ 161ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg protected static MenuAdapter toMenuAdapter(ListAdapter adapter) { 162ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg if (adapter instanceof HeaderViewListAdapter) { 163ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg return (MenuAdapter) ((HeaderViewListAdapter) adapter).getWrappedAdapter(); 164ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg } 165ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg return (MenuAdapter) adapter; 166ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg } 167ed3912692f0ba8a647d795462e20fcdb67adbacbOren Blasberg} 168