This question is about options menus inflated from Fragment
s into a Toolbar
, via Fragment#setHasOptionsMenu(true)
.
Let’s say we have an activity with 3 fragments:
FragmentA
FragmentB (with menu)
FragmentC
FragmentD (with menu)
Fragments A, B and C are part of the main activity, and are switched using FragmentTransaction#replace()
. FragmentD is actually a child fragment of FragmentC. So, in FragmentC we do like:
getChildFragmentManager().beginTransaction().replace(R.id.container, new FragmentD());
First case: going to B, then back to A
All goes well: when in B, I see the overflow icon with my menu; back in A, the icon disappears.
Second case: going to C, then back to A
When in C, D is loaded and its menu is shown; back in A, the menu is still there! Why is this? Is this a bug? How should this be addressed in a pleasant way (e.g. not a dirty specific workaround that makes your code unreadable and unscalable)?
I can find a solution myself by trying a little bit, but I am mostly interested in why this happens.
Some code
Here’s a minimal example.
This might be a FragmentC
that loads a FragmentD
:
public class FragmentC extends Fragment {
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
FragmentD f = new FragmentD();
getChildFragmentManager()
.beginTransaction()
.replace(getContainerId(), f, “tag")
.addToBackStack(“tag")
.commit();
}
}
}
This might be a menu fragment, like both FragmentB
and FragmentD
:
public class MenuFragment extends Fragment {
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.list_or_grid, menu);
}
}
FragmentA
can be whatever you want. The main activity switches through fragments using replace
(adding to back stack, for what it’s worth):
// className can be FragmentA, FragmentB or FragmentC class names
private void goToFragment(String className) {
FragmentManager f = getSupportFragmentManager();
Fragment fragment = Fragment.instantiate(this, className);
f.beginTransaction()
.replace(R.id.fragment_content, fragment, className)
.addToBackStack(className)
.commit();
}