在单击“ActionBar”项时显示弹出菜单

50

我有一个带有操作项的ActionBar。 点击操作项后,我想显示一个弹出菜单。 我实现了这种方法,但我想将其锚定到操作项或ActionBar,而不是从布局中获取视图。 如何从MenuItem获取某种视图来作为锚点呢?

public boolean onOptionsItemSelected(MenuItem item) {
    PopupMenu popupMenu = new PopupMenu(this, ??????); // What view goes here?
    popupMenu.inflate(R.menu.counters_overflow);
    popupMenu.show();
    // ...
    return true;
}

我正在做类似的事情!在这里查看:https://dev59.com/cnLYa4cB1Zd3GeqPVUK3 - Etienne Lawlor
6个回答

127

所以,最后我找到了解决方案。当你想将弹出菜单锚定到ActionBar中的ActionItem时,你需要找到呈现ActionItem的视图。 用findViewById()查找与xml中菜单项id相同的视图即可。

显示弹出菜单:

public boolean onOptionsItemSelected(MenuItem item) {
    // ...

    View menuItemView = findViewById(R.id.menu_overflow); // SAME ID AS MENU ID
    PopupMenu popupMenu = new PopupMenu(this, menuItemView); 
    popupMenu.inflate(R.menu.counters_overflow);
    // ...
    popupMenu.show();
    // ...
    return true;
}

菜单:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

     ....

     <item
    android:id="@+id/menu_overflow"
    android:icon="@drawable/ic_overflow"
    android:showAsAction="ifRoom"
    android:title="@string/menu_overflow"/>

     ....

</menu>

如果菜单项不可见(在溢出中),它将无法工作。findViewById返回null,因此您必须检查此情况并锚定到另一个视图。


12
findViewById(R.id.menu_overflow) 返回值为 null。 - ingsaurabh
9
如果你在非 Activity 的根视图中使用 findViewById(R.id.menu_overflow),它会返回 null。请改用 Activity.findViewById(R.id.menu_overflow),一切都会正常 =)) - maXp
在弹出菜单中,是否可以在特定项目之间添加分隔符? - android developer
1
无法工作。出现“不能在没有锚点的情况下使用”的错误。 - Christopher Smit
如果菜单项不可见(即为null),您可以使用工具栏视图并将其重力设置为Gravity.END,这样它将锚定到溢出菜单: setDropDownGravity(Gravity.END); setAnchorView(toolbarView); 请记住,锚点视图不能为空,否则调用show()时应用程序将崩溃。 - Miloš Černilovský
显示剩余3条评论

3
接受的答案对我没有用,所以我通过试错方法找到了问题。
public boolean onOptionsItemSelected(MenuItem item) 
{
    View menuItemView = findViewById(item.getItemId()); 
    showPopupMenu(menuItemView)

    return true;
}

private void showPopupMenu(View anchor)
{
    PopupMenu popup = new PopupMenu(this, anchor);
    popup.getMenuInflater().inflate(R.menu.my_popup_menu, popup.getMenu());
    popup.show();
}

关键在于,在 onOptionsItemSelected(MenuItem item) 方法中的 item 必须显示在 ActionBar 上。如果该 item 是出现在 ActionBar 右上方的三个垂直点按下后出现的选项之一,那么你的应用程序将崩溃。

enter image description here


0
除了被接受的答案之外,每次调用onOptionsItemSelected()方法时重新填充弹出窗口的问题可以简化为仅在第一次调用时进行,然后根据需要显示多次。
(即使是通过Menu Layout Inflater在运行时填充的自定义工具栏也适用。只需记住,findViewById()获取菜单项视图的非空值仅在视图实际存在于屏幕上时才返回,即应该在工具栏/操作栏上可见。) 注意:如果视图预设在工具栏/操作栏的溢出菜单中,则有可能只有在至少调用一次溢出菜单(使用3个点?)后才会填充视图。
public class SomeActivity{
    
    private PopupMenu popup;
    .... // some code of the activity

@Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        int menuItem = item.getItemId();
        switch (menuItem) {
            case R.id.tb_menu_plus:
                View menuItemView = findViewById(R.id.tb_menu_plus);
                if(popup == null) {
                    popup = new PopupMenu(this, menuItemView);
                    popup.inflate(R.menu.dropdown_popup_menu);
                }
                popup.show();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

enter image description here


0
如果您不希望在单击特定项目时菜单消失,请在该项目上使用return false
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId())
        {
            case R.id.itemShare_:
                onShareClicked();
                return true;    // the menu will be gone
            case R.id.itemCopy_:
                onCopyClicked();
                return true;    // the menu will be gone
            case R.id.itemSelectAll_:
                onSelectAllClicked();
                return false;   // the menu will stay

               // ...
       }

0

请尝试这个...

  @Override
public boolean onOptionsItemSelected(MenuItem item){
    String str=item.getTitle().toString(); 
    Toast.makeText(getBaseContext(), str,Toast.LENGTH_LONG). show();

    View view=findViewById(item.getItemId()); 
    switch(view.getId()){
        case Menu.FIRST:
            showPopup(view); // calling method
    }

    return super.onOptionsItemSelected(item);
}   

// custom method
private void showPopup(final View view) {
    PopupMenu popupMenu = new PopupMenu(view.getContext(), view);
    popupMenu.getMenu().add(0, 0, Menu.NONE, "Item 1");
    popupMenu.getMenu().add(0, 1, Menu.NONE, "Item 2");
    popupMenu.getMenu().add(0, 2, Menu.NONE, "Item 3");
    popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                Toast.makeText(view.getContext(), item.getTitle() + "clicked", Toast.LENGTH_SHORT).show();
                return true;
            }
        });
    popupMenu.show();
}

-5
public boolean onOptionsItemSelected(MenuItem item) {
    final View addView = getLayoutInflater().inflate(R.layout.add, null);

            new AlertDialog.Builder(this).setTitle("Add a Word").setView(addView)
                    .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int whichButton) {
                            addWord((TextView) addView.findViewById(R.id.title));
                        }
                    }).setNegativeButton("Cancel", null).show();
return (super.onOptionsItemSelected(item));
    }

在这里获取完整的源代码...

http://vimaltuts.com/android-tutorial-for-beginners/android-action-bar-tab-menu-example


抱歉,我想找到在单击ActionItem时创建PopupMenu的正确用法。不要使用变通方法。 - pcu
问题是关于PopupMenu而不是AlertDialog。 - JaydeepW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接