5

I have an ActionBarActivity and one Fragment. The Activity has no menu inflated, while the Fragment has a menu with two buttons. Fragment menu is visible, but the buttons don't react at all when tapped. At debugging I can see that both onCreateOptionsMenu() for Fragment and Activity get called, but when tapping buttons no onOptionsItemSelected() gets called, neither from Activity nor from Fragment.

Activity

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    return false;
}

Fragment

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

    mainActivity = (NavigationActivity)getActivity();

    setHasOptionsMenu(true);
}

 @Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState){
    return (ScrollView) inflater.inflate(R.layout.tutoring_detail, container, false);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.query_details_menu, menu);

    super.onCreateOptionsMenu(menu, inflater);

}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.accept_query:
            respondToQuery(true);
            return true;
        case R.id.decline_query:
            respondToQuery(false);
            return true;
        default:
            break;
    }

    return false;
}

Menu to be displayed in Fragment

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"

<item
    android:id="@+id/accept_query"
    android:orderInCategory="100"
    app:showAsAction="always"
    android:checkable="true"
    style="?android:attr/borderlessButtonStyle"
    app:actionViewClass="android.widget.ImageButton"/>

<item
    android:id="@+id/decline_query"
    android:orderInCategory="101"
    app:showAsAction="always"
    android:checkable="true"
    style="?android:attr/borderlessButtonStyle"
    app:actionViewClass="android.widget.ImageButton"/>
</menu>
blavi
  • 531
  • 1
  • 10
  • 26

7 Answers7

4

In the Activity class,

 @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);   
                return false;
}

In the Fragment,

@Override
    public void onCreate(@Nullable 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) {
    Toast.makeText(getActivity(), "called " + item.getItemId(), Toast.LENGTH_SHORT).show();
    return super.onOptionsItemSelected(item);
}
Clevester
  • 169
  • 1
  • 4
3

You must use super.onOptionsItemSelected(item) in the parent activity's onOptionsItemSelected(...) method.

From Activity | Android Developers:

Derived classes should call through to the base class for it to perform the default menu handling.

d3dave
  • 1,361
  • 14
  • 23
2

Try moving setHasOptionsMenu(true) inside of the onCreateView() method in your Fragment instead of onCreate().

Bidhan
  • 10,607
  • 3
  • 39
  • 50
  • Thanks, but onOptionsItemSelected() still doesn't get called. I've tried both proposed solutions, separately and together but no change. – blavi Jun 07 '15 at 09:52
1

I had a similar issue after making special layout for my action button (I made an Image Button and needed to pad it and change some other things so I had to use layout for it). Then onOptionsItemSelected lost connection with this imageButton so I just use clickListener for it inside onCreateOptionsMenu. It might not be the best practice, maybe there is a better solution, but this is what solve my problem.

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
    inflater.inflate(R.menu.picker_list_menu, menu);

    MenuItem itemDone = menu.findItem(R.id.menu_done);
    MenuItemCompat.setActionView(itemDone, R.layout.menu_layout_done);
    menuDoneIB = (ImageButton) MenuItemCompat.getActionView(itemDone);
    itemDone.getActionView().setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
            //your code..
       }
     });
 }
Udi Reshef
  • 1,083
  • 1
  • 11
  • 14
  • Thanks. I also have a special menu button with changing badge text. And also cannot invoke menu click over it. In my case I have a toolbar inside activity and change badge text in onPrepareOptionsMenu. However if I change in menu_fragment.xml `app:showAsAction="withText"` or `"never"`, so that an item becomes hidden over 3 vertical dots, it becomes clickable (because we can click over item caption). Still no progress, and if I will fix, I will write. – CoolMind Aug 26 '16 at 16:12
  • Though I could make it with onPrepareOptionsMenu, a better way is written near: http://stackoverflow.com/a/39174874/2914140. – CoolMind Aug 26 '16 at 21:32
0

Try using oncreateview

public static class ExampleFragment extends Fragment {
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.example_fragment, container, false);
    }
}
0

If you have dynamically changed menu item, for instance, a badge menu (https://stackoverflow.com/a/16648170/2914140 or https://stackoverflow.com/a/26017587/2914140), you should initialize the item in onCreateOptionsMenu and re-set setOnClickListeners after every change of the item. In my case:

private MenuItem menuItem;

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.menu_catalog, menu);

    menuItem = menu.findItem(R.id.action_badge);
    writeBadge(0);

    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.action_badge) {
        // Your code.
        return true;
    }
    return super.onOptionsItemSelected(item);
}

private void writeBadge(int count) {
    MenuItemCompat.setActionView(menuItem, R.layout.item_badge);
    RelativeLayout layout = (RelativeLayout) MenuItemCompat.getActionView(menuItem);
    // A TextView with number.
    TextView tv = (TextView) layout.findViewById(R.id.badge);
    if (count == 0) {
        tv.setVisibility(View.INVISIBLE);
    } else {
        tv.setVisibility(View.VISIBLE);
        tv.setText(String.valueOf(count));
    }
    // An icon, it also must be clicked.
    ImageView imageView = (ImageView) layout.findViewById(R.id.image);
    View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            onOptionsItemSelected(menuItem);
        }
    };
    menuItem.getActionView().setOnClickListener(onClickListener);
    imageView.setOnClickListener(onClickListener);
}
Community
  • 1
  • 1
CoolMind
  • 26,736
  • 15
  • 188
  • 224
0

I am passing the click event to fragment from the activity. This worked for me.

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    return getSupportFragmentManager().getFragments().get(getSupportFragmentManager().getFragments().size() - 1)
            .onOptionsItemSelected(item);
}
zohaib khaliq
  • 697
  • 10
  • 17