16

I've got three fragments in a viewpager.

Two of these fragments have their own version of the onCreateOptionsMenu method:

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

    // Set up 1 action button
    inflater.inflate(R.menu.home_snapshot_add, menu);
}

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

    // Set up 2 action buttons
    inflater.inflate(R.menu.home_snapshot_send, menu);
}

The home activity has a basic onCreateOptionsMenu method:

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

In the onCreate method, each fragment calls the method:

setHasOptionsMenu(true);

Each of the menu items have the tag:

android:showAsAction="always"

Seems like as I open the Activity, all three buttons appear. However, when I scroll through them, the wrong ones magically disappear. It feels like the activity is calling every Fragment's options menu on Activity creation and then changes the menu appropriately when I swipe left and right. I've checked the menus but not sure what's wrong. Anything you reckon I need to check? I'm a little out of ideas.

Thanks!

SalicBlu3
  • 1,874
  • 2
  • 19
  • 32

2 Answers2

20

In your ViewPager's OnPageChangeListener and after setting the adapter to the ViewPager, have this:

@Override
public void onPageSelected(int position){
   invalidateFragmentMenus(position);
}


private void invalidateFragmentMenus(int position){
   for(int i = 0; i < mViewPagerFragentAdapter.getCount(); i++){
      mViewPagerAdapter.getItem(i).setHasOptionsMenu(i == position);
   }
   invalidateOptionsMenu(); //or respectively its support method.
}

After setting your fragment adapter call the same method with following argument:

invalidateFragmentMenus(mViewPager.getCurrentItem());

The above statements will prevent all other fragments not to receive call on onCreateOptionsMenu() method when invalidateOptionsMenu() is called, only the currently visible fragment will receive and be able to populate the options menu.

Nikola Despotoski
  • 49,966
  • 15
  • 119
  • 148
  • 1
    Thank you for you super fast response! There were quite a few things that were wrong with my code. 1. I had setHasOptionsMenu to true for all my fragments. (your code fixed that) 2. I had a nested fragment which wasn't being caught by your code 3. The activity's own OptionsMenu was inflating its own menu as an attempt to initialize the menu. (this was removed) Thanks again! – SalicBlu3 Sep 22 '14 at 05:11
  • You can iterate over child fragments using `getChildFragmentManager()` and apply same logic and then call `invalidateOptionsMenu()` – Nikola Despotoski Sep 22 '14 at 14:45
  • 5
    Only working if, in your pager adapter, you do keep a list of fragments references. This is a pattern i personally don't like, since android has to do it for me, and the whole purpose of a pager is to free memory when we slide pages... So my adapter.getItem function only returns new fragments. – Mostrapotski Dec 03 '15 at 16:33
  • I am having the same issue resolved by setHasOptionMenu(true) in onCreate of fragment and impelementing it's onCreateOptionMenu . http://stackoverflow.com/a/43730933/3496570 – Zar E Ahmer May 02 '17 at 06:03
1

I've used this and it has worked for me:

//In your Fragment
@Override
public void onResume() {
    super.onResume();
    setHasOptionsMenu(isVisible());

}
Daniel Ben
  • 175
  • 2
  • 4
  • 11