PopupMenu.java revision b933f9c89bbe890ff6753559b83c0ecf236472dd
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.support.v7.widget; 17 18 19import android.content.Context; 20import android.support.annotation.MenuRes; 21import android.support.v7.internal.view.SupportMenuInflater; 22import android.support.v7.internal.view.menu.MenuBuilder; 23import android.support.v7.internal.view.menu.MenuPopupHelper; 24import android.support.v7.internal.view.menu.MenuPresenter; 25import android.support.v7.internal.view.menu.SubMenuBuilder; 26import android.view.Menu; 27import android.view.MenuInflater; 28import android.view.MenuItem; 29import android.view.View; 30 31/** 32 * Static library support version of the framework's {@link android.widget.PopupMenu}. 33 * Used to write apps that run on platforms prior to Android 3.0. When running 34 * on Android 3.0 or above, this implementation is still used; it does not try 35 * to switch to the framework's implementation. See the framework SDK 36 * documentation for a class overview. 37 */ 38public class PopupMenu implements MenuBuilder.Callback, MenuPresenter.Callback { 39 private Context mContext; 40 private MenuBuilder mMenu; 41 private View mAnchor; 42 private MenuPopupHelper mPopup; 43 private OnMenuItemClickListener mMenuItemClickListener; 44 private OnDismissListener mDismissListener; 45 46 /** 47 * Callback interface used to notify the application that the menu has closed. 48 */ 49 public interface OnDismissListener { 50 /** 51 * Called when the associated menu has been dismissed. 52 * 53 * @param menu The PopupMenu that was dismissed. 54 */ 55 public void onDismiss(PopupMenu menu); 56 } 57 58 /** 59 * Construct a new PopupMenu. 60 * 61 * @param context Context for the PopupMenu. 62 * @param anchor Anchor view for this popup. The popup will appear below the anchor if there 63 * is room, or above it if there is not. 64 */ 65 public PopupMenu(Context context, View anchor) { 66 mContext = context; 67 mMenu = new MenuBuilder(context); 68 mMenu.setCallback(this); 69 mAnchor = anchor; 70 mPopup = new MenuPopupHelper(context, mMenu, anchor); 71 mPopup.setCallback(this); 72 } 73 74 /** 75 * @return the {@link Menu} associated with this popup. Populate the returned Menu with 76 * items before calling {@link #show()}. 77 * 78 * @see #show() 79 * @see #getMenuInflater() 80 */ 81 public Menu getMenu() { 82 return mMenu; 83 } 84 85 /** 86 * @return a {@link MenuInflater} that can be used to inflate menu items from XML into the 87 * menu returned by {@link #getMenu()}. 88 * 89 * @see #getMenu() 90 */ 91 public MenuInflater getMenuInflater() { 92 return new SupportMenuInflater(mContext); 93 } 94 95 /** 96 * Inflate a menu resource into this PopupMenu. This is equivalent to calling 97 * popupMenu.getMenuInflater().inflate(menuRes, popupMenu.getMenu()). 98 * @param menuRes Menu resource to inflate 99 */ 100 public void inflate(@MenuRes int menuRes) { 101 getMenuInflater().inflate(menuRes, mMenu); 102 } 103 104 /** 105 * Show the menu popup anchored to the view specified during construction. 106 * @see #dismiss() 107 */ 108 public void show() { 109 mPopup.show(); 110 } 111 112 /** 113 * Dismiss the menu popup. 114 * @see #show() 115 */ 116 public void dismiss() { 117 mPopup.dismiss(); 118 } 119 120 /** 121 * Set a listener that will be notified when the user selects an item from the menu. 122 * 123 * @param listener Listener to notify 124 */ 125 public void setOnMenuItemClickListener(OnMenuItemClickListener listener) { 126 mMenuItemClickListener = listener; 127 } 128 129 /** 130 * Set a listener that will be notified when this menu is dismissed. 131 * 132 * @param listener Listener to notify 133 */ 134 public void setOnDismissListener(OnDismissListener listener) { 135 mDismissListener = listener; 136 } 137 138 /** 139 * @hide 140 */ 141 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 142 if (mMenuItemClickListener != null) { 143 return mMenuItemClickListener.onMenuItemClick(item); 144 } 145 return false; 146 } 147 148 /** 149 * @hide 150 */ 151 public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) { 152 if (mDismissListener != null) { 153 mDismissListener.onDismiss(this); 154 } 155 } 156 157 /** 158 * @hide 159 */ 160 public boolean onOpenSubMenu(MenuBuilder subMenu) { 161 if (subMenu == null) return false; 162 163 if (!subMenu.hasVisibleItems()) { 164 return true; 165 } 166 167 // Current menu will be dismissed by the normal helper, submenu will be shown in its place. 168 new MenuPopupHelper(mContext, subMenu, mAnchor).show(); 169 return true; 170 } 171 172 /** 173 * @hide 174 */ 175 public void onCloseSubMenu(SubMenuBuilder menu) { 176 } 177 178 /** 179 * @hide 180 */ 181 public void onMenuModeChange(MenuBuilder menu) { 182 } 183 184 /** 185 * Interface responsible for receiving menu item click events if the items themselves 186 * do not have individual item click listeners. 187 */ 188 public interface OnMenuItemClickListener { 189 /** 190 * This method will be invoked when a menu item is clicked if the item itself did 191 * not already handle the event. 192 * 193 * @param item {@link MenuItem} that was clicked 194 * @return <code>true</code> if the event was handled, <code>false</code> otherwise. 195 */ 196 public boolean onMenuItemClick(MenuItem item); 197 } 198}