'Fragment's onOptionsItemSelected doesn't get called

My fragment replaces the parent Activity options with a specific option item but when I click on the item, only activity's onOptionItemSelected gets called eventhough I've overridden the method inside Fragment. Am I missing something?

Fragment's methods:

@Override
public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

    Log.d(TAG, "Fragment.onCreateOptionsMenu");

    if (mPasteMode) {
        menu.clear();
        inflater.inflate(R.menu.contexual_paste, menu);
        getActivity().getActionBar().setTitle("PasteMode");
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d(TAG, "Fragment.onOptionsItemSelected");

    switch (item.getItemId()) {
        case R.id.context_action_paste:
            Toast.makeText(getActivity(),
                     "It worked ",
                    Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}

Activity's methods:

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    Log.d(TAG, "MainActivitiy.onOptionsItemSelected");
    switch (item.getItemId()) {
        case R.id.action_refresh:
            Toast.makeText(this, "Action Refresh selected", Toast.LENGTH_SHORT).show();
            break;
        default:
            break;
    }
    return true;
}

Logcat output:

MainActivity.onCreateOptionsMenu
Fragment.onCreateOptionsMenu
MainActivitiy.onOptionsItemSelected

So how can I have the onOptionsItemSelected of the fragment called?



Solution 1:[1]

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).

Solution 2:[2]

If your Activity's onOptionsItemSelected method returs true, the call is consumed in activity and Fragment's onOptionsItemSelected is not called. So, return false in your Activity onOptionsItemSelected method or parent class implementation via super.onOptionsItemSelected call (default implementation returns false).

According Activity class javadoc, method Activity.onOptionsItemSelected should:

Return false to allow normal menu processing to proceed, true to consume it here

Solution 3:[3]

In my case I did not add any menu items (i.e. I did not call onCreateOptionsMenu in either the activity or the fragment). However, I needed to use the action bar home (up) button in the fragment. For this I had to make sure that setHasOptionsMenu(true) was called in the fragment's onCreateView() method before this could work. Then I didn't need an onOptionsItemSelected override in my activity.

Solution 4:[4]

I found solution i.e

Fragment.class

 @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    // Do something that differs the Activity's menu here
    //MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.wifinity_setting, menu);
    for (int i = 0; i < menu.size(); i++) {
        MenuItem item = menu.getItem(i);
        SpannableString spanString = new SpannableString(menu.getItem(i).getTitle().toString());
        spanString.setSpan(new ForegroundColorSpan(Color.BLACK), 0, spanString.length(), 0); //fix the color to white
        item.setTitle(spanString);
    }
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {

        case R.id.menu1:
            Intent intent3 = new Intent(context, activity.class);
            startActivity(intent3);
            return true;

    }
    return true;
}

ACtivity.class

overide the onOptionsItemSelected() // fragmnets onOptionselected method get called .. this solution works for me

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {

        default:
            if(fragment != null)
                fragment.onOptionsItemSelected(item);
    }
    return true;
}

Solution 5:[5]

I agree with the currently accepted solution, but another possible cause is having an ambiguous class reference. I had a custom class in my project named MenuItem and my Fragment was interpreting that custom.MenuItem as the parameter type instead of android.view.MenuItem

The symptoms were a wiggly red underline on my Override and IDE message indicating that onOptionsItemSelected will not be called.

Solution 6:[6]

After a few hours of working on this issue, I found a solution.

You need to call onOptionsItemSelected in activity but return false like this

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return false
    }

Next step is adding setHasOptionsMenu(true) inside fragment onCreate()

And finally you can call onOptionsItemSelected in your fragment and handle menu item click

override fun onOptionsItemSelected(item: MenuItem): Boolean {
        //My awesome stuff
        return super.onOptionsItemSelected(item)
    }

That's it.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 CommonsWare
Solution 2
Solution 3
Solution 4 Sonali Kale
Solution 5 Dharman
Solution 6 thegirlincode