Correct way to handle menus

27 views Asked by At

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:

  1. Is this the correct way to handle menus?
  2. Should I use menu in each Fragment instead of MainAtivity?
  3. Why onPrepareOptionsMenu is not called in backPressed() ?

Thank you everyone.

backPressed() not updates the menu

0

There are 0 answers