【问题标题】:Android: How to include a menu xml inside another menu xml?Android:如何在另一个菜单 xml 中包含一个菜单 xml?
【发布时间】:2012-07-11 16:38:53
【问题描述】:

简单的问题。

我有我的子项目菜单:

<?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>

以后我想把它作为这个菜单的子菜单:

<?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 有点回答这个问题 - 我不知道如何扩展子菜单。

我认为您在 onContextItemSelected 方法中对其进行充气 - 但充气需要一个菜单​​对象,该对象未传递给 onContextItemSelected。

【问题讨论】:

    标签: android xml contextmenu submenu


    【解决方案1】:

    遗憾的是,这在纯 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 />
    

    您可以使用指定的inflater将上述代码放入以下任何一个:

    • Activity.onCreateContextMenu(menu, v, menuInfo): getMenuInflater()
    • Fragment.onCreateContextMenu(menu, v, menuInfo): getActivity().getMenuInflater()
    • Activity.onCreateOptionsMenu(menu): getMenuInflater()
    • 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>
    

    空的&lt;menu /&gt; 占位符非常重要,没有那个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>
    

    注意您的onContextItemSelected 想法

    我在想你在 onContextItemSelected 方法中膨胀它[...]

    我认为如果您在onContextItemSelected 中为时已晚,因为您已经在处理将导致显示您是子菜单的事件...尚未膨胀。您可以尝试对getSubMenu() 进行相同的膨胀,但我不确定它是否会出现。最好在应该创建的地方创建菜单。

    关于在同一个菜单中多次包含同一个子菜单的注意事项

    未经测试如果您还需要将相同的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());
    

    然后在on*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】:

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

      实际上,您可以将第一个菜单扩展为Menu,然后使用size()getItem(int)MenuItems 从中取出。然后,对于每个项目,您可以在第二个菜单的findItem(R.id.teameditor_assignfieldingposition)getSubMenu() 上执行add(menuItem.getGroupId(), menuItem.getItemId(), menuItem.getOrder(), menuItem.getTitle())。这应该将第一个菜单的所有项目添加为该项目的子菜单。这意味着您正在扩充两个 XML 文件,但如果您想使用单独的 XML 文件,这是不可避免的,因为菜单 XML 文件没有&lt;include&gt;。我可能会正常膨胀第二个菜单(在onCreateOptionsMenu(...) 中),然后将第一个菜单添加为onPrepareOptionsMenu(...) 中的子菜单(它给出了您在onCreateOptionsMenu(...) 中创建的菜单)。我认为您可以在onCreateOptionsMenu(...) 中完成所有操作,但我认为最好在onPrepareOptionsMenu(...) 中修改菜单。

      我认为第二种方法是我能找到的最佳解决方案,为了以防万一,我将保留第一种选择。

      【讨论】:

      • 如果您使用getSubMenu() just inflate into that directly,则无需使用add手动复制。同样获得“a [temporary] Menu [...] to get the MenuItems”也是不可能的。
      猜你喜欢
      • 2011-05-19
      • 1970-01-01
      • 2019-09-14
      • 2018-07-01
      • 2010-09-06
      • 2022-01-03
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多