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