Back navigation with Fragments / Toolbar

Hamz4h_ picture Hamz4h_ · Mar 8, 2015 · Viewed 16.2k times · Source

I'm scratching my head with this one now.... I have an ActionBarActivity that loads an initial Fragment - the original menu is inflated within the activity. Now, I have a navigation bar that, when an item is selected, loads a different fragment and adds this to the backstack.

When I do this, there are a couple of things I want to set:

  1. Set the home as up indicator
  2. Invalidate the options menu from the main activity
  3. Set has options to true for the Fragment
  4. Ensure that the up indicator correctly navigates back to the original Fragment

Something rather strange is going on - the up indicator appears once only and does not behave as the back button and although I've invalidated and inflated a new menu, the new menu gets appended to the original Activity menu.

EDIT: Ok I've resolved the appending issue - forgot to add menu.clear() in the onCreateOptionsMenu method.

My navigation drawer layout has onClick methods to all menu items which would trigger the load of another Fragment:

public void navItemClick(View view) {

        switch (view.getId()) {
            case R.id.ripSMS:
                mNavigationDrawer.toggleHome(false);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
                FragmentTransaction mTrans = getSupportFragmentManager().beginTransaction();
                mTrans.replace(R.id.voiceover_frame_layout,new MessageFragment(),"main_ui")
                        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE).addToBackStack("msg").commit();
                break;
            case R.id.ripEmail:
                break;
            case R.id.ripSettings:
                break;
        }

        mNavigationDrawer.closeDrawer();
    }

toggleHome:

public void toggleHome(boolean show) {
        mDrawerToggle.setDrawerIndicatorEnabled(show);

        if (!show) {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        } else {
            mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
        }
    }

Once the item is triggered the onCreate contains the invalidate and the hasOptions code:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getActivity().invalidateOptionsMenu();
    setHasOptionsMenu(true);
}

The onCreateOptionsMenu then inflates another menu layout (contains a single item called settings).

As mentioned, this only partially works once - the first time I use the item to load the Fragment, I get the back icon but it's also not working (this is set within onOptionsItemSelected to check for the home item press - it does nothing). When I press the back button it takes me back to the correct place. If I navigate back however, the back arrow now longer shows even though the code runs through onCreate!

Answer

Hamz4h_ picture Hamz4h_ · Mar 8, 2015

Ok so I managed to solve this after some trial and error. Two changes made:

  1. Implement addOnBackStackChangedListener
  2. ActionBarDrawerToggle's setToolbarNavigationClickListener needed to be set

As I only have one activity (everything else is Fragment classes) I added the backstack listener to the Parent Activity's onCreate method:

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            } else {
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
            }
        }
    });

This resolved the disappearing back arrow when going back to the fragment. Finally added the listener to my NavigationDrawer's setup class:

mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getActivity().onBackPressed();
            }
        });

I suppose the only questions I have is everything pointed towards using the onOptionsItemSelected method with android.R.id.home but this never worked for me. It might be the way I've implemented things of course but if someone sees anything obvious as to why please do let me know!