[翻译]  Android: How to include a menu xml inside another menu xml?

[CHINESE]  Android:如何在另一个菜单xml中包含菜单xml?


Simple question.

简单的问题。

I have my menu of child items:

我有我的儿童用品菜单:

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

    <item
        android:id="@+id/fp_pitcher"
        android:title="Pitcher">
    </item>
    <item
        android:id="@+id/fp_catcher"
        android:title="Catcher">
    </item>
<!-- SNIP ---> 
</menu>

And later I would want to include it as a submenu of this menu:

后来我想把它包含在这个菜单的子菜单中:

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


    <item
        android:id="@+id/teameditor_remove"
        android:title="Remove Player from Team">
    </item>

    <item
        android:id="@+id/teameditor_assignbattingposition"
        android:title="Assign Batting Position">
    </item>

    <item
        android:id="@+id/teameditor_assignfieldingposition"
        android:title="Assign Feilding Position">
        <!-- I want to include the submenu here-->
    </item>

</menu>

The question here kind of answered this - I'm not sure how to inflate the submenu.

这里的问题有点回答 - 我不知道如何给子菜单充气。

I'm thinking that you inflate it in the onContextItemSelected method - but inflate requires a menu object, which isn't passed into onContextItemSelected.

我想你在onContextItemSelected方法中给它充气 - 但是inflate需要一个菜单​​对象,它不会传递给onContextItemSelected。

2 个解决方案

#1


3  

It's sadly not possible in plain XML, but there's a nice way without using manual Menu.add* methods: here's how you can obtain a Menu instance to include/inflate the other file into:

遗憾的是,在纯XML中不可能,但是没有使用手动Menu.add *方法有一个很好的方法:这里是如何获得一个Menu实例来包含/膨胀其他文件到:

inflater.inflate(R.menu.player, menu);
MenuItem fp_menu = menu.findItem(R.id.teameditor_assignfieldingposition);
inflater.inflate(R.menu.positions, fp_menu.getSubMenu()); // needs <menu />

You can put the above code to any of the following using the specified inflater:

您可以使用指定的inflater将以上代码添加到以下任何代码中:

  • Activity.onCreateContextMenu(menu, v, menuInfo): getMenuInflater()
  • Activity.onCreateContextMenu(menu,v,menuInfo):getMenuInflater()
  • Fragment.onCreateContextMenu(menu, v, menuInfo): getActivity().getMenuInflater()
  • Fragment.onCreateContextMenu(menu,v,menuInfo):getActivity()。getMenuInflater()
  • Activity.onCreateOptionsMenu(menu): getMenuInflater()
  • Activity.onCreateOptionsMenu(menu):getMenuInflater()
  • Fragment.onCreateOptionsMenu(menu, inflater): inflater
  • Fragment.onCreateOptionsMenu(menu,inflater):inflater

menu/player.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/teameditor_remove"
          android:title="Remove Player from Team"
    />
    <item android:id="@+id/teameditor_assignbattingposition"
          android:title="Assign Batting Position"
    />
    <item android:id="@+id/teameditor_assignfieldingposition"
          android:title="Assign Feilding Position">
        <menu><!-- include: positions.xml --></menu>
    </item>
</menu>

The empty <menu /> placeholder is very important, without that getSubMenu() will be null!

占位符非常重要,没有getSubMenu()将为null!

menu/positions.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/fp_pitcher"
          android:title="Pitcher"
    />
    <item android:id="@+id/fp_catcher"
          android:title="Catcher"
    />
    <!-- SNIP ---> 
</menu>

Note on your onContextItemSelected idea

I'm thinking that you inflate it in the onContextItemSelected method [...]

我在想你在onContextItemSelected方法中给它充气[...]

I think it's too late if you're in onContextItemSelected, since you're already handling the event which would lead to showing you're submenu... which is not inflated yet. You could try the same inflate into getSubMenu(), but I'm not sure that it'll show up. It's best to create the menu where it's supposed to be created.

如果你在onContextItemSelected,我认为现在已经太晚了,因为你已经处理了这个事件,这会导致你显示你的子菜单......这还没有膨胀。你可以尝试相同的膨胀到getSubMenu(),但我不确定它会出现。最好创建应该创建它的菜单。

Note on including the same submenu multiple times in the same menu

Untested If you need to inflate the same positions.xml into teameditor_assignbattingposition as well you'll have some problems in onOptionsItemSelected/onContextItemSelected. One way to work around it is to convert the findItem variable to a field and save the reference to both

未经测试如果您需要将相同的positions.xml扩展到teameditor_assignbattingposition,那么在onOptionsItemSelected / onContextItemSelected中会遇到一些问题。解决此问题的一种方法是将findItem变量转换为字段并将引用保存到两者

this.fp_menu = menu.findItem(R.id.teameditor_assignfieldingposition);
inflater.inflate(R.menu.positions, fp_menu.getSubMenu());
this.bp_menu = menu.findItem(R.id.teameditor_assignbattingposition);
inflater.inflate(R.menu.positions, bp_menu.getSubMenu());

and then in on*ItemSelected:

然后在* ItemSelected上:

switch (item.getItemId()) {
    case R.id.fp_pitcher:
        if (item == fp_menu.findItem(R.id.fp_pitcher)) {
            // selected inside teameditor_assignfieldingposition
        } else if (item == bp_menu.findItem(R.id.fp_picther)) {
            // selected inside teameditor_assignbattingposition
        } else {
            throw new ImLostInMenusException();
        }
        return true;
}
return super.on*ItemSelected();

#2


0  

It's not pretty, but if you you need to do it without copying the XML content over (which would work easily). When you inflate the second menu you can also do a menu.findItem(R.id.teameditor_assignfieldingposition).getSubMenu().add(...) for each of the items you want to add. If you have the strings ("Pitcher" and "Catcher") in a String array resource you could iterate over that array to add the same items as in the original. Alternatively, you would probably need to parse the other menu's XML, you can cheat that by just inflating it I guess, and then using it's size() and getItem(int).

它并不漂亮,但如果您需要这样做而不复制XML内容(这将很容易)。当您为第二个菜单充气时,您还可以为要添加的每个项目执行menu.findItem(R.id.teameditor_assignfieldingposition).getSubMenu()。add(...)。如果在String数组资源中有字符串(“Pitcher”和“Catcher”),则可以迭代该数组以添加与原始数据相同的项目。或者,您可能需要解析其他菜单的XML,您可以通过膨胀来欺骗它,我想,然后使用它的size()和getItem(int)。

In fact, you could just inflate the first menu into a Menu and then use size() and getItem(int) to get the MenuItems out of it. Then, for each item you can do add(menuItem.getGroupId(), menuItem.getItemId(), menuItem.getOrder(), menuItem.getTitle()) on the getSubMenu() of the second menu's findItem(R.id.teameditor_assignfieldingposition). That should add all the items of the first menu as a submenu of that item. This means you are inflating two XML files, but it's kind of unavoidable if you want to use separate XML files, seeing as there isn't an <include> for menu XML files. I would probably inflate the second menu normally (in the onCreateOptionsMenu(...)) and then add the first menu as a submenu in the onPrepareOptionsMenu(...) (it's given the menu you created in onCreateOptionsMenu(...)). I think you could do it all in onCreateOptionsMenu(...), but I believe it's better practice to make modifications to the menu in onPrepareOptionsMenu(...).

实际上,您可以将第一个菜单膨胀到菜单中,然后使用size()和getItem(int)来获取MenuItems。然后,对于每个项目,你可以在第二个菜单的findItem(R.id.teameditor_assignfieldingposition)的getSubMenu()上添加(menuItem.getGroupId(),menuItem.getItemId(),menuItem.getOrder(),menuItem.getTitle())。 )。这应该将第一个菜单的所有项目添加为该项目的子菜单。这意味着你要膨胀两个XML文件,但如果你想使用单独的XML文件,那就不可避免了,因为菜单XML文件没有 。我可能会正常膨胀第二个菜单(在onCreateOptionsMenu(...)中)然后将第一个菜单添加为onPrepareOptionsMenu(...)中的子菜单(它给出了你在onCreateOptionsMenu(...)中创建的菜单) 。我认为你可以在onCreateOptionsMenu(...)中完成所有工作,但我相信最好在onPrepareOptionsMenu(...)中对菜单进行修改。

I think the second way is the best solution I can find, I'm leaving the first option as an alternative just in case.

我认为第二种方式是我能找到的最佳解决方案,我将第一种选择作为替代方案以防万一。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2018 ITdaan.com 粤ICP备14056181号