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