In Android, I create my menu item like this?
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 0, 0, "Menu1");
menu.add(0, 1, 0, "Menu2");
return true;
}
How can I set all the menu item disabled programmatically (in another part of the code in my activity, not in onCreateOptionsMenu() method itself)?
You can use the groupId you set to disable/enable all the menu items at once, using menu.setGroupEnabled(). So for example, since you added the items to group 0, you'd do:
menu.setGroupEnabled(0, false);
Also, if you want to dynamically modify the menu, you should hook into onPrepareOptionsMenu(). onCreateOptionsMenu() is only called once per Activity, so it's good for setting up the initial menu structure, but onPrepareOptionsMenu() should be used to enable/disable menus as necessary later in the Activity.
add returns a MenuItem (which you can also retrieve from the Menu object), that you can store away into a variable.
MenuItem menu1;
public boolean onCreateOptionsMenu(Menu menu) {
menu1 = menu.add(0, 0, 0, "Menu1");
}
public void someOtherMethod() {
if(menu1 != null) {
// if it's null, options menu hasn't been created, so nevermind
menu1.setEnabled(false);
}
}
I prefer to hide them completely if they should not be used (instead of disabling them).
For that I do:
menu.clear();
and to recreate it:
invalidateOptionsMenu();
This also works for menu items added from fragments.
If still relevant:
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
for(int i=0; i<menu.size(); i++){
menu.getItem(i).setEnabled(isMenuEnabled);
}
}
and call invalidateOptionsMenu() then isMenuEnabled changed
If you have multiple occasions where you want to do something with all items of a menu (for example changing the 'checked' state) there is an elegant solution using Kotlin Extension Properties:
(Building on top of the answer of Valery)
In one place define the property 'items' of android.view.Menu:
import android.view.Menu
import android.view.MenuItem
val Menu.items: List<MenuItem>
get() {
val items = mutableListOf<MenuItem>()
for (i in 0 until this.size()) {
items.add(this.getItem(i))
}
return items
}
Now you can use it on any menu:
anyMenu.items.forEach { it.isEnabled = false }
Related
I'm trying to make an app that disables the user from going to the menu. I know I have to override onPrepareOptionsMenu(Menu menu) but what do I have to put as input for menu if I want to use this function in a different function? I don't quite understand the Menu object and how many types it has.
Do something like this:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
and then call the updateOptionsMenu() function where you want
My menu has a item to Log in, but when you are logged in I want it to say Log out.
How?
If I'm going to change the item after its created, its probably through this method
#Override
public boolean onCreateOptionsMenu( Menu menu ) {
MenuInflater inflater = getMenuInflater();
inflater.inflate( R.menu.menu_main, menu );
return true;
}
Afaik the onCreateOptionsMenu() happens after the onCreate so putting any getItemId() for the menu there will give me a NullPointerException right away.
I want the app to find out if its supposed to use the string R.string.Logout if its logged in.
I dont even know what to search for for this issue. All I found was how to make a string implement names, like this answer https://stackoverflow.com/a/7646689/3064486
You should use onPrepareOptionsMenu(Menu menu) instead to update menu items
#Override
public boolean onPrepareOptionsMenu(Menu menu){
super.onPrepareOptionsMenu(menu);
MenuItem someMenuItem = menu.findItem(R.id.some_menu_item);
someMenuItem.setTitle("Log out");
return super.onPrepareOptionsMenu(menu);
}
To refresh Menu items call invalidateOptionsMenu();from Activity
From Android API guides: "If you want to modify the options menu based on events that occur during the activity lifecycle, you can do so in the onPrepareOptionsMenu() method. This method passes you the Menu object as it currently exists so you can modify it, such as add, remove, or disable items. (Fragments also provide an onPrepareOptionsMenu() callback.)"
After you inflate a menu, you can customize its items. To get each one, you must call findItem() with the item's id. In particular, you can use setTitle() to change the displayed string.
For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
if (mIsLoggedIn)
menu.findItem(R.id.action_login).setTitle("Log out");
return true;
}
where action_login is the id you set for this particular menu item in the menu's xml file.
private void updateUI() {
runOnUiThread(new Runnable() {
#Override
public void run() {
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
Menu menu = navigationView.getMenu();
MenuItem nav_signin = menu.findItem(R.id.nav_signin);
nav_signin.setTitle(MyApp.signedIn ? "Sign out" : "Sign in");
}
});
}
Is there any option to detect a click in overflow menu?
I don't want to detect clicking in particular items.
As it was posted in this other question, you can do the following:
#Override
public boolean onMenuOpened(int featureId, Menu menu) {
if(featureId == AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR){
Toast.makeText(this, "OPEN", Toast.LENGTH_SHORT).show();
}
return super.onMenuOpened(featureId, menu);
}
#Override
public void onPanelClosed(int featureId, Menu menu) {
if(featureId == AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR){
Toast.makeText(this, "CLOSE", Toast.LENGTH_SHORT).show();
}
super.onPanelClosed(featureId, menu);
}
If you are inheriting from AppCompat. If not, the right constant to be used is Window.FEATURE_ACTION_BAR
Are you simply trying to detect when the options menu itself is made visible? If so, I believe the "onPrepareOptionsMenu" method on Activity is your best bet.
Prepare the Screen's standard options menu to be displayed. This is
called right before the menu is shown, every time it is shown. You can
use this method to efficiently enable/disable items or otherwise
dynamically modify the contents.
The default implementation updates the system menu items based on the
activity's state. Deriving classes should always call through to the
base class implementation.
http://developer.android.com/reference/android/app/Activity.html#onPrepareOptionsMenu(android.view.Menu)
The is a problem that affects platforms prior to 3.0, i.e. when Sherlock acts as a proxy to provide the action bar menu items.
I have a Fragment Activity that contains two fragments, each with its own set of options menus. When the activity starts the first fragment tab is shown and its menu items work normally. However, the first time that I switch to the other tab its menu items do not respond. If I switch back to the first tab and select the other tab again they start to fire normally.
It looks like this is a known problem. Check out the discussion here.
My workaround for now is to detect the first time that the second tab is selected and programatically switch back to the first tab. This forces the user to select the second tab again, but from that point on it works normally, as long as the user stays in that activity.
I am wondering if anyone else has found a more elegant solution to this problem. Thanks!
First fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
moveMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.MOVE_FLASHES_ID, 0, R.string.move_flashes);
cloneMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.CLONE_FLASHES_ID, 0, R.string.clone_flashes);
deleteMenuItem = menu.add(Flashum.MENU_GROUP_MULTI, Flashum.DELETE_FLASHES_ID, 0, R.string.delete_flashes);
moveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
moveMenuItem.setIcon(R.drawable.move2red);
cloneMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
cloneMenuItem.setIcon(R.drawable.hard_drive_clone);
deleteMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
deleteMenuItem.setIcon(R.drawable.delete);
}
Second fragment:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
saveMenuItem = menu.add(Flashum.MENU_GROUP_SAVE, Flashum.SAVE_CHANGES_ID, 0, R.string.save_changes);
saveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
saveMenuItem.setIcon(R.drawable.save);
menu.setGroupVisible(Flashum.MENU_GROUP_SAVE, true);
recMenuItem = menu.add(Flashum.MENU_GROUP_REC, Flashum.RECORD_ID, 0, R.string.record);
recMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
recMenuItem.setIcon(R.drawable.microphonehot);
}
Try to clear your menu before you inflate it in your fragments. So in your fragments in onCreateOptionsMenu methods call menu.clear(); at the beginning and then inflate your menu.
Something like this:
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
menu.clear();
saveMenuItem = menu.add(Flashum.MENU_GROUP_SAVE, Flashum.SAVE_CHANGES_ID, 0, R.string.save_changes);
saveMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
saveMenuItem.setIcon(R.drawable.save);
menu.setGroupVisible(Flashum.MENU_GROUP_SAVE, true);
recMenuItem = menu.add(Flashum.MENU_GROUP_REC, Flashum.RECORD_ID, 0, R.string.record);
recMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
recMenuItem.setIcon(R.drawable.microphonehot);
}
Try it in both of your fragments.
Instead of detecting when the second tab is selected, switch the fragments programmatically in the onCreate of your Activity using a post delayed method. For example I have 3 fragments and I switch them in reverse order (2, 1, 0) and it fools your users with a nice animation at the beginning of the Activity:
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.HONEYCOMB){
mIndicator.setCurrentItem(2);
mIndicator.postDelayed(new Runnable() {
public void run() {
mIndicator.setCurrentItem(1);
mIndicator.postDelayed(new Runnable() {
public void run() {
mIndicator.setCurrentItem(0);
}}, 100);
}}, 100);
}
In some methods of my Activity I want to check the title of menu or know if it is checked or not. How can I get Activity's menu. I need something like this.getMenu()
Be wary of invalidateOptionsMenu(). It recreates the entire menu. This has a lot of overhead and will reset embedded components like the SearchView. It took me quite a while to track down why my SearchView would "randomly" close.
I ended up capturing the menu as posted by Dark and then call onPrepareOptionsMenu(Menu) as necessary. This met my requirement without an nasty side effects. Gotcha: Make sure to do a null check in case you call onPrepareOptionsMenu() before the menu is created. I did this as below:
private Menu mOptionsMenu;
#Override
public boolean onCreateOptionsMenu(final Menu menu) {
mOptionsMenu = menu
...
}
private void updateOptionsMenu() {
if (mOptionsMenu != null) {
onPrepareOptionsMenu(mOptionsMenu);
}
}
Call invalidateOptionsMenu() instead of passing menu object around.
you could do it by passing the Menu object to your Activity class
public class MainActivity extends Activity
{
...
...
private Menu _menu = null;
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
_menu = menu;
return true;
}
private Menu getMenu()
{
//use it like this
return _menu;
}
}
There several callback methods that provide menu as a parameter.
You might wanna manipulate it there.
For example:
onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
onCreateOptionsMenu(Menu menu)
onCreatePanelMenu(int featureId, Menu menu)
There several more, best you take a look in activity documentation and look for your desired method:
http://developer.android.com/reference/android/app/Activity.html
As far as I could understand what you want here is which may help you:
1. Refer this tutorial over option menu.
2. Every time user presses menu button you can check it's title thru getTitle().
3. Or if you want to know the last menu item checked or selected when user has not pressed the menu button then you need to store the preferences when user presses.
Android now has the Toolbar widget which was a Menu you can set/get. Set the Toolbar in your Activity with some variation of setSupportActionBar(Toolbar) for stuff like onCreateOptionsMenu from a Fragment for example. Thread revived!