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;
}
Related
In the new update Google has released a new API support library, that supports the ActionBar in API level 7+.
I used ActionBarSherlock until this update and I wrote the code to load the menu:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_main, menu);
return true;
}
and the menu file:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/item_menu_ok" android:icon="#drawable/ic_action_ok"
android:title="#string/ok" android:showAsAction="always"></item>
<item android:id="#+id/item_menu_cancel" android:icon="#drawable/ic_action_cancel"
android:title="#string/cancel" android:showAsAction="always"></item>
</menu>
To set up the menu buttons on the action bar. This code worked perfectly with ActionBarSherlock. But when I changed the action bar to the new support library, the buttons are not shown in the action bar. Even if they are set as android:showAsAction="always". And when I debug the code, the function menu.getSize() return 2, and that is correct, but no buttons are shown..
Why are the buttons not shown in the new support library?
Try pressing the MENU button on your device or emulator, and see if they appear in the overflow.
If they do, then the problem is that your <menu> XML needs to change. Menu XML that works with ActionBarSherlock and the native API Level 11+ action bar will not work with the AppCompat action bar backport.
Your menu XML would need to look like this:
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:yourapp="http://schemas.android.com/apk/res-auto"
>
<item android:id="#+id/item_menu_ok" android:icon="#drawable/ic_action_ok"
android:title="#string/ok" yourapp:showAsAction="always"></item>
<item android:id="#+id/item_menu_cancel" android:icon="#drawable/ic_action_cancel"
android:title="#string/cancel" yourapp:showAsAction="always"></item>
</menu>
And you would need to use the same yourapp prefix for anything else related to the action bar (e.g., yourapp:actionLayout).
You can see this covered in the action bar documentation.
I'd like to add a little to the answer.
If you want to see both text and an icon, please use withText in showAsAction
I've just tested it; when I used always or ifRoom without withText, I only saw an icon.
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.
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.
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"
Many of menus have always one item same to all.
Is there the way to define that item as extra menu and include it to all other?
Something like this:
menu/main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/menu_main"
android:title="#string/text_mainmenu" />
</menu>
menu/other.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
parent="#menu/main">
<item android:id="#+id/menu_other"
android:title="#string/text_othermenu" />
</menu>
I know, that it's possible to do it programmaticaly, but I thought xml-way is nicer.
Inflating each menu and calling to super works great!
Here is an example:
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.main, menu);
getMenuInflater().inflate(R.menu.other, menu);
return true;
}
You can control the order if super also adds more items by calling it before/after other inflates, or not call at all it to ignore those items.
AFAIK, <include> only works for layout XML, not menu XML, though you can certainly give it a try. Lacking that, the programmatic option (inflating both menu XML files) is the only option I am aware of.