Android: How to include a menu xml inside another menu xml? - android

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.

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();

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).
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(...).
I think the second way is the best solution I can find, I'm leaving the first option as an alternative just in case.

Related

How to change the order of MenuItems in menu of NavigationView in code?

I have a menu in NavigationView that have 7 menu items, some of these menu items should be invisible based on user settings and the remaining visible items should be displayed in different order. the items are already defined in the XML menu layout.
I've googled a lot but nothing related to already defined menu items. most of the solutions was suggesting to create the menu items in code and set the order while creating it.
here is my menu items XML layout:
<group android:checkableBehavior="single">
<item
android:id="#+id/Home_menuitem"
android:title="Home" />
<item
android:id="#+id/Register_menuitem"
android:title="Register" />
<item
android:id="#+id/Login_menuitem"
android:title="Login" />
<item
android:id="#+id/language_menuitem"
android:title="Language" />
<item
android:id="#+id/ContactUs_menuitem"
android:title="Contact Us" />
<item
android:id="#+id/Likes_menuitem"
android:title="Likes" />
<item
android:id="#+id/Subscription_menuitem"
android:title="Subscription" />
<item
android:id="#+id/Logout_menuitem"
android:title="Logout" />
</group>
say I want to change the order in Code (NOT in XML) to make "Likes_menuitem" to be displayed above "Home_menuitem"
I didn't try it but you probably can follow these steps.
Get a reference to the menu first
navigationView.getMenu()
Add or remove specific items to (from) it with different order to achieve your order.
add(int groupId, int itemId, int order, CharSequence title)
removeItem(int id)
More information in the docs!
If you add items programmatically just change the order of adding items. Even if you change the position of menu inflating it will affect the result order.
menu.add(Menu.NONE, 898, Menu.NONE, "Item title") // <- Will be 1st
inflater.inflate(R.menu.menu_progress_avatar, menu) // <- Will be 2nd
You can do this by visible menuitem to true or false.

general menu for all layout android

i have a photo sharing apps which display bottom menu in all layout i have create one but is display when i press menu key i want menu which display when any activity start
so how can i create general menu for all layout and no need to press menu key for display bottom menu bar android
thanks
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_bookmark"
android:icon="#drawable/icon_bookmark"
android:title="Bookmark" />
<item android:id="#+id/menu_share"
android:icon="#drawable/icon_share"
android:title="Share" />
<item android:id="#+id/menu_delete"
android:icon="#drawable/icon_delete"
android:title="Delete" />
</menu>
activity.java
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater menuInflater = getMenuInflater();
menuInflater.inflate(R.layout.menu, menu);
return true;
}
Instead of creating Menu you have to make a common custom xml layout for your menu and include it with your all activity's layout xml file. For this you can use <merge> and <include> tag of Android XML Layout.
Look at Layout Tricks: Merging Layouts
Layout Tricks: Creating Reusable UI Components
Update:
Now on your question, To open a Menu without pressing Menu Button, you can put this line in your onCreate() of Activity.
openOptionsMenu();
And to close:
closeOptionsMenu();
These both methods for Activity class, So if you are using it out-side of activity then use context of Activity and with this method.

Inheritance and extension of XML (menu) resources

Is it possible to inherit and extend XML resources in android easily, specifically for menus.
For example. if my base_menu.xml is
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/item_manual_input"
android:title="#string/manual_input/">
<item android:id="#+id/item_logoff"
android:title="#string/logoff"/>
</menu>
Both options I'd like to reuse elsewhere (in another activity). instead of repeating the tags for the items in base_menu, I'd very much like to do something like this for inheriting_menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<menu android:id="#id/base_menu"/>
<item android:id="#+id/extra_option"
android:title="#string/extra_option/>
</menu>
but I don't see anything similar to this in any documentation. Is anything like this supported, or am I stuck with using fragments to limit code and XML replication for various XML resources? (I believe this would work, but I haven't used fragments yet)
Not possible for menus but doable for layouts.
See include tag: https://developer.android.com/training/improving-layouts/reusing-layouts.html
For the menu:
You can work around in the code by inflating menu xml files and adding single menu items:
#Override public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.base, menu); // All menus in base.xml
getMenuInflater().inflate(R.menu.extras, menu); // base.xml + extras.xml
menu.add("More"); // base.xml + extras.xml + "More"
return true;
}

Checks not showing in Options Menu

Sometimes when doing some so very simple, you miss something big. I must be missing something huge because I am getting nowhere fast (and an hour of sifting through the web has revealed nothing).
I want to have a menu with items with checkmarks in group--just like a simple RadioGroup layout. I get the menu, but no checkmarks of any kind.
Here's the res/menu/options_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<group android:checkableBehavior="single">
<item
android:id="#+id/item1"
android:title="item1"
/>
<item
android:id="#+id/item2"
android:title="item2"
/>
<item
android:id="#+id/item3"
android:title="item3"
android:checked="true"
/>
</group>
</menu>
And of course, here's the relevant methods in my Activity:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
This is about as simple as I can make it--any ideas on what I'm missing?
I think you try to create Options Menu (it's displayed by click menu button) and according to this
Note: Menu items in the Icon Menu (from the Options Menu) cannot
display a checkbox or radio button. If you choose to make items in the
Icon Menu checkable, you must manually indicate the checked state by
swapping the icon and/or text each time the state changes.
you can't add group menu in OptionsMenu. so i think you shoud use Context Menu or Submenu.
Take a look at this article
Here's the work-around:
In your strings.xml file you can embed a unicode checkmark. There are two to choose from. For this project I prefer the friendlier check of \u2714. You then swap a string with the check-mark for a string without it via onPrepareOptionsMenu() as appropriate.
Here's the xml code two strings, one with and one without checkmarks:
<string name="opp_random">unchecked</string>
<string name="opp_random_check">\u2714 checked</string>
Happy coding!
How about
android:checkable="true"

Element ITEM is not allowed in MENU

I'm trying to make a customized options menu. After using this code I get: Element item is not allowed here
Code:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<item android:id="#+id/morsoid_settings"
android:icon="#drawable/ic_new_game"
android:title="#string/new_game" />
<item android:id="#+id/morsoid_close"
android:icon="#drawable/ic_help"
android:title="#string/help" />
</menu>
Inspired by: Android dev guide
I dont know whether it makes a difference, but did you place you menu in res/menu and not in res/layout?
Try leaving out the layout attributes. Here is the example from the documentation:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/new_game"
android:icon="#drawable/ic_new_game"
android:title="#string/new_game" />
<item android:id="#+id/help"
android:icon="#drawable/ic_help"
android:title="#string/help" />
</menu>
Edit - also make sure you are using a MenuInflater as the guide suggests:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
Using a LayoutInflater will cause <menu> to be interpreted as a view element, when it is actually a menu resource.
Not 100% sure you are talking about a compile error, or the errors shown in your development system while in the layout file.
Using Idea IntelliJ (10.5) I got that error while pasting the example code shown above into the menu.xml file.
However after building the project, it disappeared. I still see the layout_width / height errors you see when editing the menu.xml file but it does not affect the build or runtime behaviour.
This is kind of an old question but I thought I'd put my solution here since I experienced this in 2019:
I was getting a warning in Android Studio saying "Element item is not allowed here" when putting an <item> inside a <menu>. It turns out my problem was that in my src/main/res/layout folder, rather than in my src/main/res/menu folder.

Categories

Resources