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

62

我可以通过xml在ActionBar中添加子菜单项。

enter image description here

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代码添加这些子项?下面的代码不起作用,子项被添加到了错误的操作中(并且也没有显示可绘制对象),即最右侧的按钮而不是我的“New Form”按钮:

图像描述

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代码添加子菜单项,而不使用PopupMenu (http://developer.android.com/guide/topics/ui/menus.html#PopupMenu)并实现这一目标?

更新(解决方案):

最终我所得到的代码片段是为了动态地填充子菜单,遵循adamp的回答:

// 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;
}

1
我在我的应用程序中使用以下代码:@Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.poi_menu, menu); for (int i = 0; i < name.length; i++) { menu.getItem(0).getSubMenu() .add(0, Menu.NONE, i, name[i] + " (" + type[i] + ")") .setIcon(R.drawable.zoomin); } return true; } 但是图标仍然没有出现... - Chirag Patel
3个回答

36

可以的。

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

例如:

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来实现这一点,认为这是它们的目的,并将项目挂在正确的层次结构中。再次感谢。 - Mathias Conradt
组ID用于其他形式的逻辑分组。例如,如果菜单项以“ifRoom”的形式出现在操作栏中,则同一组中的项目将一起溢出 - 要么组中的所有项目都将出现在栏中,要么所有项目都将移动到溢出菜单中。这对于不应在演示中分开的相关命令非常有用。 - adamp
1
@MathiasLin 你是怎么解决这个问题的?因为我也面临同样的问题。但正如adamp建议的那样,它在主菜单中添加了子菜单(在主菜单中新建表单),然后我们点击“新建表单”,它显示“表单1”项目,但尽管如此,绘图仍未出现。你能分享一些代码吗? - Chirag Patel
@chiragsaga 我按照adamp的提示操作,对我来说效果很好。我将在我的原始问题中更新/添加代码。 - Mathias Conradt
4
如果有人想往已经存在于XML中的子菜单中添加项目,可以使用“menu.getItem(<index>).getSubMenu().add("menu item");”。请注意,翻译内容不得包含解释或其他非翻译相关的信息。 - C--

2

添加一个ActionProvider可能更容易。您可以按照这里的说明进行尝试。


1
你应该考虑使用ActionProvider。
示例:https://gist.github.com/sibelius/7ca0b757492ff6740dec 带有ActionProvider项的菜单。
<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();
    }
}

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