Reputation: 2472
I have an activity (AppCompatActivity) (called Activity) and two fragments (called Fragment A and Fragment B).
When Activity is lunched, I use setContentView
and Fragment A was generated.
When I try to start Activity with specific parameter I lunch Fragment B. Fragment A and Fragment B has the same layout, I change only the data to be rendered.
In Fragment A, I have a menu with 1 item, this one performs an action on my view: change list to a grid layout.
In fragment B, I have this menu too, but, when I click on the item nothing changes. So I've tried this in debug mode. I've seen that when I press item in the menu, for Fragment B, this called menu action of Fragment A.
How can I resolve this cycle?
Upvotes: 0
Views: 54
Reputation: 54274
When you select a menu item, the system will dispatch that event to the active Activity
as well as all currently active Fragment
s. The event will be dispatched to the Fragments in the order they were added to the Activity.
If Fragment A and Fragment B both include an onOptionsItemSelected()
implementation that handles the same R.id
constant, this will cause the problem you're seeing.
For example, imagine Fragment A has this code:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_settings) {
// do some Fragment A thing
}
...
}
And imagine Fragment B has this code:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_settings) {
// do some Fragment B thing
}
...
}
Even if the user clicks on R.id.action_settings
inside Fragment B, the system will dispatch the event to Fragment A, and Fragment A will happily handle it!
There are a few different solutions to this problem.
First, you could change your menus in your two fragments so that they have the same text labels but use different android:id
attributes (and then update your Fragment code accordingly). Now only the "right" fragment will be able to handle the item selection event.
Second, you could update your onOptionsItemSelected()
code to determine whether the Fragment is currently active, and ignore the event if it is not:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (!isAdded() || !isVisible()) {
return false;
}
if (item.getItemId() == R.id.action_settings) {
// do some Fragment A thing
}
}
Finally, you could use dynamically-generated IDs for your menu items. I'd recommend against this approach as it is much more complicated than the others.
Upvotes: 1