What are the two parameters Menu and menu in method onCreateOptionsMenu(Menu menu) and how to use this method.
I have another question why this parameter is used in
Intent intent = new Intent(this, DisplayMessageActivity.class);
Menu is just the type of the parameter menu. For example you can have a String type for a variable named string, dog, etc. And in this case there's a Menu type for a parameter named menu.
You use onCreateOptionsMenu() to specify the options menu for an activity.
In this method, you can inflate your menu resource (defined in XML) into the Menu provided in the callback.
For example:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
Fore more information, visit this link.
As for this,
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called.
For example:
public void sendMessage() {
Intent intent = new Intent(this, DisplayMessageActivity.class);
}
The constructor takes two parameters and a Context as its first parameter.
this represents environment data and provides global information about an application environment.
For more information on the intent example you provided, check this out.
The intent of implementing this method is to populate the menu passed with the items you define in the R.menu.game_menu layout file.
#Java
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.game_menu, menu);
return true;
}
#Kotlin
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.game_menu, menu)
return true
}
After inflating the menu with the items you might want to add some action when they are selected:
Java
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item:
// Action goes here
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Kotlin
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.menu_item -> {
// Action goes here
true
}
else -> super.onOptionsItemSelected(item)
}
}
When onCreateOptionsMenu is called?
onCreateOptionsMenu() is called by the Android runtime when it need to create the option menu.
Android Developer Guide: Menus
If you've developed your application for Android 2.3.x and lower, the system calls onCreateOptionsMenu() to create the options menu when the user opens the menu for the first time. If you've developed for Android 3.0 and higher, the system calls onCreateOptionsMenu() when starting the activity, in order to show items to the app bar.
How to build an option menu?
Please refer to other anwsers.
Why onCreateOptionsMenu return Boolean
Activity.html#onCreateOptionsMenu
You must return true for the menu to be displayed; if you return false it will not be shown.
Why onOptionsItemSelected return Boolean
When you successfully handle a menu item, return true. If you don't handle the menu item, you should call the superclass implementation of onOptionsItemSelected() (the default implementation returns false).
Related
i have three menu items "enable, diable, exit". what i want to do is, when the R.id.menu_enable_bt is chosen, i want to disable it using
menu.findItem(R.id.menu_enable_bt).setVisible(false);
but i can not call
menu.findItem(R.id.menu_enable_bt).setVisible(false);
from inside the onOptionsItemSelected(..) method.
how can i change the visibility of a menu item inside onOptionsItemSelected(..)
CODE:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
Log.w(TAG, SubTag.msg("onCreateOptionsMenu"));
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
if (this.mBTAdapter.isEnabled()) {
menu.findItem(R.id.menu_enable_bt).setVisible(false);
menu.findItem(R.id.menu_disable_bt).setVisible(true);
} else {
menu.findItem(R.id.menu_enable_bt).setVisible(true);
menu.findItem(R.id.menu_disable_bt).setVisible(false);
}
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
Log.w(TAG, SubTag.msg("onOptionsItemSelected"));
switch (item.getItemId()) {
case R.id.menu_enable_bt:
Log.d(TAG, SubTag.bullet("onOptionsItemSelected", "menu_enable_bt"));
//menu.findItem(R.id.menu_enable_bt).setVisible(false); **how to do this**
this.mATEnableBT = new ATEnableBT();
this.mATEnableBT.execute();
break;
case R.id.menu_disable_bt:
Log.d(TAG, SubTag.bullet("onOptionsItemSelected", "menu_disable_bt"));
break;
case R.id.menu_exit:
Log.d(TAG,SubTag.bullet("onOptionsItemSelected", "menu_exit"));
finish();
break;
}
return super.onOptionsItemSelected(item);
}
you can use invalidateOptionsMenu() which will forse onCreateOptionsMenu to be called again.
From the documentation
Declare that the options menu has changed, so should be recreated. The
onCreateOptionsMenu(Menu) method will be called the next time it needs
to be displayed.
There you can check your conditions and undertake the needed actions
See the javadoc for onPrepareOptionsMenu. This is your opportunity to make changes to a menu just before it becomes visible to the user. So you should maintain some member variables describing what should be visible and use that to modify the menu items here.
I'm tring to change a menuitem icon, but the icon is not being changed.
Here is how I find the MenuItem (works fine):
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.activity_location_actions, menu);
mActionLocation = menu.findItem(R.id.action_location);
return super.onCreateOptionsMenu(menu);
}
Method UpdateIcon: I took a screenshot so you can see (in the red frame) that the images have been found by the system.
The mActionLocation is a MenuItem which is initialized before this Method is called and is not null.
Anyone has an idea?
UPDATE (solution by help from #vinitius)
The UpdateIcon method:
private void UpdateIcon(boolean locationOn) {
mActionLocation = locationOn; // mActionLocation is a global boolean
invalidateOptionsMenu();
}
The onPrepareOptionsMenu override:
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
// Toggle location icon
if (mActionLocation) {
menu.findItem(R.id.action_location).setIcon(R.drawable.ic_location_on_white_24dp);
} else {
menu.findItem(R.id.action_location).setIcon(R.drawable.ic_location_off_white_24dp);
}
return super.onPrepareOptionsMenu(menu);
}
You need to use onPrepareOptionsMenu(Menu menu):
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.
Inside this method, retrieve your item as you do in onCreateOtionsMenu and check whether your gps in os or not to modify your item icon.
I have a fragment class that extends Fragment and calls setHasOptionsMenu to participate in the menu. This class also implements onCreateOptionsMenu, onPrepareOptionsMenu and onOptionsItemSelected.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
....
}
I'm dynamically loading this fragment using a FragmentTransaction in my Activity (that extends FragmentActivity).
However none of the menu callbacks (onCreateOptionsMenu, onPrepareOptionsMenu and onOptionsItemSelected) are being called (I've debugged with some breakpoints in those methods) and the menu isn't shown.
Am I missing something? Do I need to add something in my Activity?
I'm using the Android Compatibility Library, compiling with L11 SDK and testing in a Xoom.
EDIT: I've found the problem. My AndroidManifest is targeting L11, this seems to hide the menu button and prevent from the callbacks being called. However if I remove this from the manifest I loose some other features I need (for example the activated state in lists). Does anyone know how to solve this issue (enable the menu button) without removing the targetSdkVersion=11 from the Manifest?
Aromero,
Don't forget to override the onCreateOptionsMenu using the fragment version of the method, similar to this:
#Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.queue_options, menu);
super.onCreateOptionsMenu(menu, inflater);
}
This goes in the fragment, by the way, and adds to the inflated menu of the Activity, if there is one. Had the same problem myself, until I figured this out.
Kim
If you're having this problem with ActionBarSherlock, you need to make sure your Fragments are SherlockFragments, not mere SupportFragments, and that what you're overriding is
public void onPrepareOptionsMenu (com.actionbarsherlock.view.Menu menu) {
NOT
public void onPrepareOptionsMenu (android.view.Menu menu) {
If you do the latter, you should get some sort of warning about the function being final and you being unable to override it. This is a warning that you're trying to override the wrong function!
If you fix the error by switching the class from SherlockFragment to a mere Fragment, you can create the function . . . but it won't get called.
I had the same problem, but i think its better to summarize and introduce the last step to get it working:
Add setHasOptionsMenu(true) method in your Fragment's onCreate(Bundle savedInstanceState) method.
Override onCreateOptionsMenu(Menu menu, MenuInflater inflater) (if you want to do something different in your Fragment's menu) and onOptionsItemSelected(MenuItem item) methods in your Fragment.
Inside your onOptionsItemSelected(MenuItem item) Activity's method, make sure you return false when the menu item action would be implemented in onOptionsItemSelected(MenuItem item) Fragment's method.
An example:
Activity
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.activity_menu_item:
// Do Activity menu item stuff here
return true;
case R.id.fragment_menu_item:
// Not implemented here
return false;
default:
break;
}
return false;
}
Fragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
....
}
#Override
public void onCreateOptionsMenu(Menu menu) {
// Do something that differs the Activity's menu here
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.activity_menu_item:
// Not implemented here
return false;
case R.id.fragment_menu_item:
// Do Fragment menu item stuff here
return true;
default:
break;
}
return false;
}
I hope this will be helpful.
Cheers.
If you have an activity and a fragment that each loads menu items then you need to take special care of which overrides you use.
Activities can override onOptionsItemSelected and onMenuItemSelected, however fragments can only override onOptionsItemSelected.
If you override onMenuItemSelected in your activity and onOptionsItemSelected in your fragment, your fragment override will never get triggered.
Instead, use onOptionsItemSelected in both activity and fragment.
You need to make sure you call setHasOptionsMenu(true); onCreate or onCreateView is called in your fragment.
You also need to implement the override of onCreateOptionsMenu inside your fragment.
Another possible case is when you use a common id for a common action in each fragment; for instance R.id.action_add
Today I had such situation: hitting the option menu [add] was invoked the "wrong" onOptionItemSelected because each fragment (replaced dynamically using a DrawerLayout) had the same R.id.action_add.
Short story, if you have such situation always check that your fragment is visible:
if (!isVisible()) return false;
Long story, pay attention at the onOptionItemSelected chain!
MainActivity
|
| onOptionItemSelected
+-----------------------
| return false
|
MyCoolFragment1
|
| onOptionItemSelected
+-----------------------
| return false
|
MyCoolFragment2
|
| onOptionItemSelected
+-----------------------
| return true
|
[item selection handled]
If you add your fragments with (something like) this:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, MyCoolFragment1.newInstance())
.commit()
and you have defined the same id for a common action (let's say R.id.action_add) in each fragment;
don't forget to add this line to each: if (!isVisible()) return false;
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isVisible()) return false; // <-- Not visible? skip!
if (item.getItemId() == R.id.action_add) {
//.TODO whatever
return true; //.Handled!
}
return false; //.Skip
}
I had this problem when I was using the ViewPagerIndicator in conjunction with ActionBarSherlock. Although it appeared this was fixed I still ran into the problem. The work around I found was to call into the fragment manually.
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
Toast.makeText(this, "From activity", Toast.LENGTH_SHORT).show(); // TODO
Fragment currentFragment = mAdapter.getItem(mPager.getCurrentItem());
if (currentFragment != null && currentFragment instanceof SherlockFragment)
{
((SherlockFragment)currentFragment).onOptionsItemSelected(item);
}
return super.onOptionsItemSelected(item);
}
I've found the problem. The AndroidManifest is targeting SDK 11, this seems to hide the menu button and prevent from the callbacks being called. I assume that this breaks the compatibility of the menu button that seems to be replaced by the action bar in Android 3.0
I think you have implemented onCreateOptionsMenu, onPrepareOptionsMenu and onOptionsItemSelected in the class that extends Fragment. Try by doing that in your Activity class where you are loading this fragment
From the android developer site - link
Note: If you inflate menu items from a fragment, via the Fragment
class's onCreateOptionsMenu() callback, the system calls
onOptionsItemSelected() for that fragment when the user selects one of
those items. However, the activity gets a chance to handle the event
first, so the system first calls onOptionsItemSelected() on the
activity, before calling the same callback for the fragment. To ensure
that any fragments in the activity also have a chance to handle the
callback, always pass the call to the superclass as the default
behavior instead of returning false when you do not handle the item.
Therefore Marco HC is the best answer of all.
If your toolbar is defined in the parent activity xml, make sure you do this in your fragment
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
....
Toolbar toolbar = (Toolbar)getActivity().findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
setHasOptionsMenu(true);
}
And then of course, override onCreateOptionsMenu like below
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.edit_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
This is the only solution that worked for me!
I had same problem and solution that worked for me is:
Remove or comment any onOptionsItemSelected() ,onMenuItemSelected() even onPrepareOptionMenu() and leave in Activity onCreateOptionsMenu() only:
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater=getMenuInflater();
inflater.inflate(R.layout.menu, menu);
return true;
}
In Fragment class, in onCreateView(), put:
setHasOptionsMenu(true);
In Fragment class add :
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu,inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.action_insert:
//doing stuff
return true;
}
return false;
}
Tested and worked on Android 4.4
I need to enable a MenuItem when a previous screen (Activity) returns.
I tried this code:
...
((MenuItem)findViewById(R.id.menu_how)).setEnabled(true);
...
but a null pointer exception is launched.
BTW, the menu_how is set to false in xml; and the code is part of onActivityResult(int requestCode, int resultCode, Intent data) call.
Try using menu.findItem(R.id.menu_how) in onCreateOptionsMenu and save a reference for later use.
This should work fine with enabled, however, I've found that setting a menu item to invisible in the XML means you can't show/hide it programmatically.
I found something at the android dev site that might be helpful (look for the section "Changing menu items at runtime")
It said that the onCreateOptionsMenu() method fired only when the the menu for the activity is created, and it happens when this activity starts. So if you want to change the menu items after the menu/activity was created, you need to override the onPrepareOptionsMenu() method instead. search the link for full details.
EDIT:
Just made it and it's working fine. I'm using one boolean var per menuItem which represents if this item should be enabled or not. This is my code:
/*************************************Game Menu**************************************/
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId())
{
case R.id.gm_new_game:
//newGame();
return true;
case R.id.gm_stand_up:
//some code when "gm_stand_up" button clicked..
return true;
case R.id.gm_forfeit:
//some code when "gm_forfeit" button clicked..
return true;
case R.id.gm_surrender:
//some code when "gm_surrender" button clicked..
return true;
case R.id.gm_exit_table:
exitTableCommand();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onPrepareOptionsMenu(Menu menu)
{
menu.findItem(R.id.gm_forfeit).setEnabled(forfeitMenuButtonIsEnabled);
menu.findItem(R.id.gm_surrender).setEnabled(surrenderMenuButtonIsEnabled);
menu.findItem(R.id.gm_new_game).setEnabled(newGameMenuButtonIsEnabled);
menu.findItem(R.id.gm_stand_up).setEnabled(standUpMenuButtonIsEnabled);
return super.onPrepareOptionsMenu(menu);
}
where are you calling this? (Sorry, didn't read carefully) I think you need to call it after the menu is inflated (usually in OnCreateOptionsMenu). To do this, you can set a variable to true when the other Activity returns, then do ((MenuItem)findViewById(R.id.menu_how)).setEnabled(mMyBooleanField) in OnCreateOptionsMenu after the call to inflater.inflate.
Edit: To accomplish this in code, it might look something like this:
At the top of the class (along with all the other class members):
Boolean mEnableMenuItem = false;
In OnCreateOptionsMenu:
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_main, menu);
((MenuItem)findViewById(R.id.menu_how)).setEnabled(mEnableMenuItem );
In OnActivityResult:
mEnableMenuItem = true;
Keep a reference to Menu in your activity:
private Menu mMenu;
Then:
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_note, menu);
mMenu = menu;
return true;
}
Now, to access menu items anywhere in your activity use similar code to this:
mMenu.findItem(R.id.menu_how).setVisible(false);
or
mMenu.findItem(R.id.menu_how).setEnabled(true);
I have 10-15 activities in my project. I want to have the option menu mostly in all Activities. Then is their any way we can do it at one place and it appears in all activities.
Also, I will like to hide the option menu in some. So, is it possible or I have to write option menu code in all activities.
Regards
Sunil
Create a Class (say BaseActivity) that extends Activity, and override onCreateOptionsMenu and onOptionsItemSelected functions.
public class BaseActivity extends Activity {
// Activity code here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item:
// do what you want here
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
Now, in the other 15-16 activities, instead of extending an Activity, you should extend BaseActivity.
public class FooActivity extends BaseActivity {
// Activity code here
}
This way, all your activities derive the options menu. For activities where you want the options menu disabled, you can override it again in that particular activity.
public class BarActivity extends BaseActivity {
// Activity code here
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Do Nothing
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Do Nothing
}
}
Hopefully, it doesn't give you problems in the manifest file.
The solution to this problem is in your new activity add this menu method.
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_home_page, menu);
menu.removeItem(R.id.logout);
return true;
}
In each activity this method will automatically appear.
If it doesn't then add it with the inflate call. It requires two parameters, an xml resource(the same one that you used in your original activity), and the menu object that is pass into the onCreateOptionsMenu method.
menu.removeItem will remove the menu item of whatever resource id you pass to it.
I hope this helps those who are facing this problem.
Thank you, and happy to share this post.
It is not enough to just extend the BaseActivity, you must also call super.onCreateOptionsMenu(menu) and super.onOptionsItemSelected(item) like this in your other activities:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
//getMenuInflater().inflate(R.menu.menu_second, menu); <- remove this
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
return super.onOptionsItemSelected(item);
}