Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fragment not receiving menu callbacks

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?

like image 716
aromero Avatar asked Jun 08 '11 13:06

aromero


4 Answers

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

like image 181
user553456 Avatar answered Nov 10 '22 13:11

user553456


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.

like image 25
Catherine Darrow Avatar answered Nov 10 '22 13:11

Catherine Darrow


I had the same problem, but i think its better to summarize and introduce the last step to get it working:

  1. Add setHasOptionsMenu(true) method in your Fragment's onCreate(Bundle savedInstanceState) method.

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

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

like image 9
Marco Hernaiz Avatar answered Nov 10 '22 14:11

Marco Hernaiz


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.

like image 6
Error 454 Avatar answered Nov 10 '22 13:11

Error 454