Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to include a menu xml inside another menu 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.

like image 654
dwjohnston Avatar asked Jul 11 '12 23:07

dwjohnston


People also ask

How do I insert one XML file into another Android?

Probably you will have to set within the include tag the properties that sets where it has to be placed: android:layout_above, android:layout_toLeftOf, etc... Use fill_parent instead. I pasted my code and I am working with honeycomb, thats why I was using match_parent. But it should work with fill_parent.

In what directory or folder would you put your menu XML file?

If you don't have this directory, and you are using Android Studio you can right click the res directory, then click new , then Android Resource Directory . In the pop-up window write menu as Directory name, and select menu for Resource type, and finally click OK . Inside this directory you can put all your menu.


1 Answers

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:

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:

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

The empty <menu /> placeholder is very important, without that getSubMenu() will be 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 [...]

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.

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

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:

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();
like image 184
TWiStErRob Avatar answered Sep 27 '22 19:09

TWiStErRob