3

I have a navigation drawer implemented but the problem is when the back button is pressed, the checked item in the draw does not correspond to the current fragment (only the last fragment that was actually added through the nav drawer)

There is a solution to this here: Updating the Navigation Drawer (with DrawerLayout) when back button is pressed

The solution states the following:

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                FragmentManager fm = getSupportFragmentManager();
                String stackName = null;
                for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
                    stackName = fm.getBackStackEntryAt(entry).getName();
                    Log.i("BC", "stackEntry" + entry);
                }
                if (stackName == "Fragment1"){
                    mDrawerList.setItemChecked(0, true);
                } else if (stackName == "Fragment2") {
                    mDrawerList.setItemChecked(1, true);
                }

            });

The issue with that is the conditional. Having to manually change the index of the nav item to be checked is a pain when you have a lot of items

What I want to do is listen for a change in the backstack, and if detected, get the id of the current fragment (as defined in the layout file) and pass that through to navigationView.setCheckedItem() to automatically check the corresponding nav item. Something like this:

navigationView = (NavigationView) findViewById(R.id.nav_view);

navigationView.setCheckedItem(R.id.nav_new);

In my mainactivity class, how do I get the id of the current fragment in the form R.id.xxx so I can pass it through to setCheckedItem?

Community
  • 1
  • 1
Simon
  • 9,762
  • 15
  • 62
  • 119

2 Answers2

0

You could do this

While adding the fragment do this

FragmentTransaction.addToBackStack(""+R.id.nav_new); // Use the id of navigation item which was clicked.

Then

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        FragmentManager fm = getSupportFragmentManager();
        String stackName = null;
        for(int entry = 0; entry < fm.getBackStackEntryCount(); entry++){
            stackName = fm.getBackStackEntryAt(entry).getName();
            Log.i("BC", "stackEntry" + entry);
        }

        int navItemId = -1;
        try{
            navItemId = Integer.parseInt(stackName);    
        } catch(NumberFormatException nfe) {
        }

        if(navItemId > 0){
            navigationView = (NavigationView) findViewById(R.id.nav_view);
            navigationView.setCheckedItem(navItemId);
        }
        else
            Log.e("", "Couldn't find the id");
    });

NOTE: Whatever you will pass in addToBackStack will be returned back to you when you will use getName() on FragmentManager.BackStackEntry

Rohit5k2
  • 17,948
  • 8
  • 45
  • 57
  • I have appended the id when adding to backstack, and used the code above exactly but I keep hitting the number format exception during the try block. I think it's because stackName looks like `NewFragment2131492999`. Does parseInt actually trip out the characters? I cant think of another reason for the exception – Simon Feb 25 '16 at 18:58
  • 1
    ok I fixed it by using `stackName.replaceAll("[\\D]", "")` in `parseInt()` – Simon Feb 25 '16 at 19:02
  • I don't understand why it would have additional string. As per documentation it should returned exactly what is passed. Is your fragments class `NewFragment`? – Rohit5k2 Feb 25 '16 at 19:02
  • 1
    It was because when I added to the backstack I was doing `addToBackStack(fragment.getClass().getSimpleName() + id)` – Simon Feb 25 '16 at 19:11
  • Oh... Thank god, documentation is not wrong. I was wondering what happened. :D – Rohit5k2 Feb 25 '16 at 19:14
0
you can handle it manually.
Make a function in base class to highlight desired item like
mDrawerList.setItemChecked(INDEX NUMBER, true);

Trick is make a model class for side menu items in which INDEX NUMBER is saved.
When you replace new fragment call that function and store currentFragment a well.
and when you press back button ovverides

 public boolean onKeyDown(int keyCode, KeyEvent event) {}
and call below function

public void popAFragment(){
 FragmentManager fragmentManager = getSupportFragmentManager();
        if(fragmentManager != null){
            int c = fragmentManager.getBackStackEntryCount();
            if(c>0){
                currentFragment = (BaseFragment) fragmentManager.getFragments().get(c-1);
                fragmentManager.popBackStack();
                setPosition(currentFragment.INDEX_NUMBER);
            }
            else {
finish();
}
}
Khizar Hayat
  • 3,427
  • 3
  • 18
  • 22