如何在代码中将子菜单项添加到 ActionBar 操作?

Posted

技术标签:

【中文标题】如何在代码中将子菜单项添加到 ActionBar 操作?【英文标题】:How to add submenu items to ActionBar action in code? 【发布时间】:2012-03-09 19:00:24 【问题描述】:

通过 xml,我可以在 ActionBar 中将子菜单项添加到我的操作中。

main_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_new_form"
          android:icon="@drawable/ic_new_form"
          android:title="@string/menu_new_form"
          android:showAsAction="ifRoom|withText">
        <menu>
            <item android:id="@+id/form1"
                  android:icon="@drawable/attachment"
                  android:title="Form 1"
                  android:onClick="onSort" />
            <item android:id="@+id/form2"
                  android:icon="@drawable/attachment"
                  android:title="Form 2"
                  android:onClick="onSort" />
        </menu>
    </item>
</menu>

但是如何通过 Java 代码添加这些子项?它不起作用,如下所示,子项目被添加到错误的操作中(并且drawable也没有显示),非常正确的按钮,而不是我的“新表单”按钮:

main_menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/menu_new_form"
          android:icon="@drawable/ic_new_form"
          android:title="@string/menu_new_form"
          android:showAsAction="ifRoom|withText">
    </item>
</menu>

Java 代码:

@Override
public boolean onCreateOptionsMenu(Menu menu) 
    super.onCreateOptionsMenu(menu);
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);

    Log.d("MainMenu", ",menu title0: " + menu.getItem(0).getTitle()); 
    // returns "New Form"

    menu.addSubMenu(0, Menu.NONE, 1, "Form 1").setIcon(R.drawable.attachment);
    menu.addSubMenu(0, Menu.NONE, 2, "Form 2").setIcon(R.drawable.attachment);
    return true;

有没有办法实现这一点,通过 Java 代码而不是 XML 添加子菜单项,不使用使用PopupMenu (http://developer.android.com/guide/topics/ui/menus.html#PopupMenu)?

更新(解决方案):

我的最终代码 sn-p 我最终动态填充子菜单,遵循 adam 的回复:

// menu options
private static final int MENU_PREFERENCES = Menu.FIRST;
private static final int MENU_LOGOUT = 2;

@Override
public boolean onCreateOptionsMenu(final Menu menu) 
    super.onCreateOptionsMenu(menu);

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    menu.add(0, MENU_PREFERENCES, 0, getString(R.string.general_preferences)).setIcon(
            android.R.drawable.ic_menu_preferences);

    // load all available form templates
    Cursor c = managedQuery(FormsProviderAPI.FormsColumns.CONTENT_URI, null, null, null, null);
    try 
        int ixDisplayName = c.getColumnIndex(FormsProviderAPI.FormsColumns.DISPLAY_NAME);
        int ixId = c.getColumnIndex(FormsProviderAPI.FormsColumns._ID);
        int cnt = 0;
        while (c.moveToNext()) 
            cnt++;
            Log.d("ID: ", "ID: "+ c.getInt(ixId));  // misusing the group id for the form id
            menu.getItem(1).getSubMenu().addSubMenu(c.getInt(ixId), Menu.NONE, cnt, c.getString(ixDisplayName)).setIcon(R.drawable.attachment_dark);
        
     catch (Exception e) 
        Log.e(TAG, "Error init form templates list.", e);
    

    return true;

【问题讨论】:

我将此代码用于我的应用程序 @Override public boolean onCreateOptionsMenu(Menu menu) // TODO 自动生成的方法存根 super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.poi_menu, menu); for (int i = 0; i 【参考方案1】:

是的,有。

addSubMenu 方法返回一个SubMenu 对象。 SubMenu 也是 Menu,因此您可以在其上调用 add 以将项目添加到子菜单而不是父菜单。您上面的代码是为 Form 1 和 Form 2 创建两个不同的子菜单,而不是在一个 New Form 子菜单中创建两个项目。

例子:

SubMenu submenu = menu.addSubMenu(0, Menu.NONE, 1, "New Form").setIcon(R.drawable.ic_new_form);
submenu.add("Form 1").setIcon(R.drawable.attachment);

【讨论】:

谢谢,我昨天已经想通了,现在开始工作了。我认为我可以使用 groupIds,认为这是他们的目的,他们将项目挂到正确的层次结构中。再次感谢。 组 ID 用于其他形式的逻辑分组。例如,如果菜单项在操作栏中显示为“ifRoom”,则同一组中的项目将一起溢出 - 组中的所有项目都将出现在栏中,或者所有项目都将移动到溢出菜单。它对于在演示中不应分开的相关命令很有用。 @MathiasLin 你是如何解决这个问题的?因为我也面临同样的情况。但是正如adamp建议的那样,它在主菜单中添加了子菜单(主菜单中的新表单),然后我们点击“新表单”,它显示“表单1”项目,但即使没有出现drawable。你能分享一些代码吗? @chiragsaga 我遵循了 adamp 的提示,它对我来说很好用。我将更新/添加原始问题中的代码。 如果有人正在寻找将项目添加到 XML 中已经存在的子菜单,请使用 menu.getItem(&lt;index&gt;).getSubMenu().add("menu item");【参考方案2】:

添加一个 ActionProvider 可能会更容易。您可以按照here的说明尝试

【讨论】:

【参考方案3】:

您应该考虑使用 ActionProvider

示例:https://gist.github.com/sibelius/7ca0b757492ff6740dec

带有操作提供程序项的菜单

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <item android:id="@+id/action_companies"
        android:icon="@drawable/ic_list"
        android:title="@string/action_companies"
        app:actionProviderClass="com.example.MyActionProvider"
        app:showAsAction="always"/>
</menu>

代码

public class MyActionProvider extends ActionProvider 

    private Context mContext;

    public MyActionProvider(Context context) 
        super(context);

        mContext = context;
    

    @Override
    public View onCreateActionView() 
        //LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        return null;
    

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) 
        super.onPrepareSubMenu(subMenu);

        subMenu.clear();

        subMenu.add("menu 1");
        subMenu.add("menu 2");
        subMenu.add("menu 3");
    

    @Override
    public boolean hasSubMenu() 
        return true;
    

    @Override
    public boolean onPerformDefaultAction() 
        return super.onPerformDefaultAction();
    

【讨论】:

以上是关于如何在代码中将子菜单项添加到 ActionBar 操作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在c ++ win32 API中将图标添加到菜单项[重复]

如何在 Delphi XE2 中将菜单项添加到 Mac OS Finder

如何在 Tkinter 中将单选按钮添加到子菜单

ActionBar 菜单项在嵌套片段中消失

如何在 Android 中将选项菜单添加到 Fragment

如何在Android中将菜单设置为工具栏