I have an Options Menu on my Activity
with an MenuItem
"Start". When this MenuItem
is selected I would like to alter the Menu so it contains a MenuItem
"Stop". And finally when "Stop" is selected, I would like to alter back to "Start".
Here is parts of my code that isn't working. I have both "Start" and "Stop" listed in mymenu.xml
I should probably remove "stop" when the menu is created:
public class MyActivity extends Activity {
private boolean isStarted = false;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
menu.removeItem(R.id.stop);
inflater.inflate(R.menu.mymenu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.start:
isStarted = true;
return true;
case R.id.stop:
isStarted = false;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(isStarted) {
menu.removeItem(R.id.start);
menu.add(R.id.stop);
} else {
menu.removeItem(R.id.stop);
menu.add(R.id.start);
}
return true;
}
}
For this type of operation I usually choose not to alter the menu items, but just hide the ones you don't need:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.start).setVisible(!isStarted);
menu.findItem(R.id.stop).setVisible(isStarted);
return true;
}
Flygenring answer is correct, but menu.findItem() is laggy and calling it within onPrepareOptionsMenu(Menu menu) produces bad user experience. It's better to get MenuItem object once while creating menu, and then just call setVisible each time menu occures on screen:
MenuItem mDynamicMenuItem;
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
// Get dynamic menu item
mDynamicMenuItem = menu.findItem(R.id.menu_item);
return true;
}
// 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.
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
// Here is just a good place to update item
mDynamicMenuItem.setVisible(isVisible);
return true;
}
You probably need to call super.onPrepareOptionsMenu after you are finished making your changes. From the docs:
Deriving classes should always call
through to the base class
implementation.
I got the solution. You are basically deleting the MenuItem
when calling removeItem()
thus also deleting the reference. Using this code works.
private boolean isStarted = false;
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
isStarted = true;
return true;
case 0:
isStarted = false;
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if(isStarted) {
menu.removeItem(1);
menu.add(0, 0, 0, "Stop");
} else {
menu.removeItem(0);
menu.add(0, 1, 0, "Start");
}
return super.onPrepareOptionsMenu(menu);
}
You have to create the MenuItem
again. Thats also the reason for the false
label. Actually you don't need the MenuInflater
as you create the Menu
via code so also no need for any menu XML file.
thanks for the info in this post as it solved my problem of the false labels in my menu. I did have to modify it slightly and have the final code that works well as follows in the hope it saves someone else some time and frustration. Its a slightly different solution but the main change I made was the .setVisible to either True or False, apart from that i.shadrins solution was the best fit for my needs.
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
if(loggedIn)
{
logIn.setVisible(false);
logOut.setVisible(true);
}
else
{
logIn.setVisible(true);
logOut.setVisible(false);
}
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
logIn = menu.findItem(R.id.loggedOut);
logOut = menu.findItem(R.id.loggedIn);
return true;
}
On Android 3.0 and higher, you should call invalidateOptionsMenu() to request that the system calls onPrepareOptionsMenu(). You can then modify the options menu in the method. You can check the Changing menu items at runtime section of the Android documentation here https://developer.android.com/guide/topics/ui/menus#options-menu for more details.