In my application I have one Activity: MainActivity that extends AppCompatActivity.
Now I have three fragments: NewHome, Settings, BatchDelete.
On run I replace my FrameLayout with NewHome:
if (savedInstanceState == null && !mDir.equals("")) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, new NewHome(), NewHome.class.getSimpleName())
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
}
I have added a back callback:
getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
public void handleOnBackPressed() {
mHideMenu = false;
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
MainActivity.super.supportInvalidateOptionsMenu();
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStackImmediate();
} else {
finish();
}
}
});
In this MainActivity I create my meny with four items: Search, Filter, Batch Delete and Settings. Search and Filter is handled in NewHome Fragment, so when user click on search, it shows a searchview and handle filter() in fragment, and when filter is clicked it shows a layout in the fragment.
When user click on Batch Delete or Settings I handle those click in menu:
int itemId = item.getItemId();
if (itemId == android.R.id.home) {
super.getOnBackPressedDispatcher().onBackPressed();
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(false);
if (getSupportFragmentManager().getBackStackEntryCount() == 0 ) mHideMenu = false;
supportInvalidateOptionsMenu();
return true;
} else
BatchDelete batchDelete = (BatchDelete) getSupportFragmentManager().findFragmentByTag(BatchDelete.class.getSimpleName());
if (batchDelete == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, new BatchDelete())
.addToBackStack(BatchDelete.class.getSimpleName())
.setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
mHideMenu = true;
supportInvalidateOptionsMenu();
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
}
} else if (itemId == R.id.menu_settings) {
Settings settings = (Settings) getSupportFragmentManager().findFragmentByTag(Settings.class.getSimpleName());
if (settings == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, new Settings())
.addToBackStack(Settings.class.getSimpleName())
.setTransition(androidx.fragment.app.FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
mHideMenu = true;
supportInvalidateOptionsMenu();
}
}
and this is my onPrepareOptionsMenu:
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
if (mHideMenu) {
menu.findItem(R.id.menu_search).setVisible(false);
menu.findItem(R.id.batch_delete).setVisible(false);
menu.findItem(R.id.menu_filter).setVisible(false);
menu.findItem(R.id.menu_settings).setVisible(false);
} else {
menu.findItem(R.id.menu_search).setVisible(true);
menu.findItem(R.id.batch_delete).setVisible(true);
menu.findItem(R.id.menu_filter).setVisible(true);
menu.findItem(R.id.menu_settings).setVisible(true);
}
return super.onPrepareOptionsMenu(menu);
}
So I have this behavior: When click on Settings it shows Settings Fragment, and show Home (back) in Toolbar and hides other menu items.
When user click home (android.R.id.home), it correctly popBackStackImmediate() and Menu is correcly updated.
But when I go back (system gesture or navbar), it correctly popBackStackImmediate() but Menu is not updated.
So the questions are:
- Is this the correct way to handle menus?
- Should I use menu in each Fragment instead of MainAtivity?
- Why onPrepareOptionsMenu is not called in backPressed() ?
Thank you everyone.
backPressed() not updates the menu