Reputation: 5212
EDIT: This question was for the deprecated sherlock action bar. Android support library should be used instead now
I have added an action bar menu option called share for my fragment
which appears but the selection event is not being caught
I am adding it like this
@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, 7,0, R.string.share);
item.setIcon(R.drawable.social_share).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
Trying to capture it in both the fragment
and the fragment activity
like
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 7:
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("text/plain");
share.putExtra(Intent.EXTRA_TEXT, "I'm being sent!!");
startActivity(Intent.createChooser(share, "Share Text"));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
and I have setHasOptionsMenu(true);
in the onCreate()
.
Upvotes: 84
Views: 70905
Reputation: 1015
From the documentation, it should solve by this steps:
If you in Activity Using the addMenuProvider() API directly:
class ExampleActivity : ComponentActivity(R.layout.activity_example) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Add menu items without overriding methods in the Activity
addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
})
}
}
If you in Fragment Using the addMenuProvider() API
class ExampleFragment : Fragment(R.layout.fragment_example) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// The usage of an interface lets you inject your own implementation
val menuHost: MenuHost = requireActivity()
// Add menu items without using the Fragment Menu APIs
// Note how we can tie the MenuProvider to the viewLifecycleOwner
// and an optional Lifecycle.State (here, RESUMED) to indicate when
// the menu should be visible
menuHost.addMenuProvider(object : MenuProvider {
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
// Add menu items here
menuInflater.inflate(R.menu.example_menu, menu)
}
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
// Handle the menu selection
return true
}
}, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
Upvotes: 5
Reputation: 1
you must add this code toolbar.bringToFront();
next set toolbar in your activity
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
...
Toolbar toolbar = findViewById(R.id.toolbar);
toolbar.setTitle("Yazd");
setSupportActionBar(toolbar);
toolbar.bringToFront(); // <<= add here
...
Upvotes: 0
Reputation: 361
You are not chaining to the superclass in the activity methods. Please have onCreateOptionsMenu() return super.onCreateOptionsMenu(menu), and have onOptionsItemSelected() return super.onOptionsItemSelected(item) (except for the item that you are handling, which should return true to indicate that you have handled the event)
Upvotes: 0
Reputation: 61
I have noticed that the solution people gave you was to implement the code for your menue item in the activity rather then the fragment. I think it will look much more orgenized if you had implemented the code in the fragment rather then the activity 'cos in my opinion it looks better. To do so, do as follows :
Activity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInTheMenueOfTheActivity:
{
//something();
break;
}
default:
//do something default and add the code under :
return super.onOptionsItemSelected(item);
}
return true;
}
Fragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{
case R.id.SomeIDInFragmentMenue:
{
break;
}
default:
return super.onOptionsItemSelected(item);
}
return true;
}
Now the lines (and the likes): "return super.onOptionsItemSelected(item);" in the activity and fragment are super important, because as if you will follow the code in debug, you will see that the menue events functions will be called first on the Activity, and if the item did not match the id's in the activity's switch-case, the degault line : "super.onOptionsItemSelected(item);" will call the onOptionsItemSelected function on the fragment, as we wanted. (if you have many fragments, make sure to have that line in them as well, as the calling hirarchy can be somewhat complicated).
Upvotes: 6
Reputation: 5878
I had the same problem, but I think it's 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 Activity's onOptionsItemSelected(MenuItem item)
method, make sure you return false
when the menu item action would be implemented in Fragment's onOptionsItemSelected(MenuItem item)
method.
An example:
@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;
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
....
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// 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;
}
Upvotes: 131
Reputation: 1094
it's so simple you can do that in your fragment to make sure that your action will listen correctly:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
Upvotes: 2
Reputation: 5212
Edit for actionbar sherlock use
I had to use
public boolean onMenuItemSelected(int featureId, MenuItem item) {
in the main activity to capture the menu item
Upvotes: 2
Reputation: 1156
I had this problem. It was because I was overiding the wrong method
onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) is what I used.
Make sure you are using the right one!
Upvotes: 0
Reputation: 1070
I'm using actionbarsherlock. This worked for me:
1) Create dummy_menu.xml menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="fill_parent" >
<item
android:title=""
android:showAsAction="never"
android:id="@+id/dummyMenu"
/>
2) In activity inflate the menu like this:
@Override
public boolean onCreateOptionsMenu(com.actionbarsherlock.view.Menu menu) {
com.actionbarsherlock.view.MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.dummy_menu,menu);
return super.onCreateOptionsMenu(menu);
}
3) In fragments onCreateView call setHasOptionsMenu(true) and override onCreateOptionsMenu and onOptionsItemSelected also hide the dummyMenu like this (in fragment)
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_actions, menu);
MenuItem item = menu.findItem(R.id.dummyMenu);
item.setVisible(false);
super.onCreateOptionsMenu(menu, inflater);
}
Hope it helps someone.
Upvotes: 2
Reputation: 1624
Same problems happened to me:
onMenuItemSelected events didn't get called in Fragment
Searched google cann't find a solution, and add onMenuItemSelected method in FragmentActivity doesn't solve it.
Finally resolve it by following reference to http://developer.android.com/guide/topics/ui/actionbar.html
Note: If you added the menu item from a fragment, via the Fragment class's onCreateOptionsMenu callback, then the system calls the respective onOptionsItemSelected() method for that fragment when the user selects one of the fragment's items. However the activity gets a chance to handle the event first, so the system calls onOptionsItemSelected() on the activity before calling the same callback for the fragment.
Which means only if you don't have that menu item handler in onOptionsItemSelected() on the activity, the onOptionsItemSelected() on the fragment will be called.
Code as following -----Remove the handler for R.action.add on FragmentActivity):
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
popBackStack();
return true;
case R.id.action_search:
searchAction();
return true;
case R.id.action_logout:
userLogout();
return true;
//case R.id.action_add:
//return true;
default:
return super.onOptionsItemSelected(item);
}
}
And the handler for R.action.add on Fragment looks like this:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Log.d("onOptionsItemSelected","yes");
switch (item.getItemId()) {
case R.id.action_add:
add();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Finally, remember to add
setHasOptionsMenu(true);
in your onCreate method in Fragment
Upvotes: 145