change navigation drawer selected item on fragment backstack change
Asked Answered
R

3

13

I have two fragments FragmentHome and FragmentAbout, I have added NavigationDrawer to app when I click Home it opens FragmentHome and About opens FragmentAbout, when I open FragmentAbout I am also adding it to backstack. This is working fine.

Now the problem is when I click on About and press back button it goes to the FragmentHome but the NavigationDrawer still shows the About as selected item, I want to change this selected item to Home when I press back button from FragmentAbout

Home Activity:

public class ActivityHome extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

Toolbar toolbar;

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    // Toolbar
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    // Drawer layout
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.nav_drawer_open, R.string.nav_drawer_close);
    assert drawer != null;
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    // Navigation view
    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    assert navigationView != null;
    navigationView.setNavigationItemSelectedListener(this);

    // Open first menu item
    navigationView.getMenu().performIdentifierAction(R.id.nav_home, 0);

    // Set first item checked
    navigationView.setCheckedItem(R.id.nav_home);
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {

    final MenuItem menuItem = item;

    // Check if menu item is selected
    if (item.isChecked())
        item.setChecked(false);
    else
        item.setChecked(true);

    // Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_home) {

        // Open home fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, new FragmentHome())
                .commit();

    } else if (id == R.id.nav_about) {

        toolbar.setTitle("About");

        // Open home fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.frame_layout, new FragmentAbout())
                .addToBackStack(null)
                .commit();

    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    assert drawer != null;
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.nav_drawer_layout);
    assert drawer != null;
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}}

FragmentHome

public class FragmentHome extends Fragment {

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_home, container, false);
}

@Override
public void onResume() {
    super.onResume();
    ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(R.string.fragment_home_title);
}
}

FragmentAbout code is same as FragmentHome just layout change.

I have searched a lot on stackoverflow but didn't find any solution yet, so if someone know how to do this please tell me.

Rubinrubina answered 10/5, 2016 at 9:55 Comment(3)
the NavigationDrawer still shows the About as selected item..for this are you talking about the toolbar title??????Pettis
@Saurabh No not toolbar title, toolbar title is working as expected, I want to change highlited menu item in drawer to Home.Rubinrubina
did you find it ??Mossbunker
B
15

There is a OnBackStackChangedListener that you can use for this. Tried it and it works great.

public Fragment getCurrentFragment() {
    return this.getSupportFragmentManager().findFragmentById(R.id.fragment_container);
}

@Override
protected void onCreate(Bundle savedInstanceState) {
   ...
   this.getSupportFragmentManager().addOnBackStackChangedListener(
       new FragmentManager.OnBackStackChangedListener() {
          public void onBackStackChanged() {
              Fragment current = getCurrentFragment();
              if (current instanceof MyFragmentA) {
                 navigationView.setCheckedItem(R.id.nav_myfragA);
              } else {
                 navigationView.setCheckedItem(R.id.nav_myfragB);
           }
       }
   });
...
}
Bronchia answered 28/8, 2016 at 17:2 Comment(2)
This method works, but if you use the same fragment for different items, it will be mistaken. Also if you open a DialogFragment (instead of fragment) and close it, this event won't be called.Arielle
@Arielle for same fragments, you can compare tagsPester
O
0

This might not be a good solution, but at least it is acceptable for me. You need to store fragment's position inside stack variable (ex: List) whenever a fragment menu is clicked from nav drawer. Then override onBackPressed to remove the last value from stack, and set drawer position to the current last value of stack. Here's the example:

private List<Integer> itemPositionStacks = new ArrayList<>();

protected void onCreate(@Nullable Bundle savedInstanceState) {
    itemPositionStacks.add(currentSelectedPosition);
}

public void onNavigationViewItemSelected(int itemId) {
        Fragment fr = null;
        switch (itemId) {
            case 0:
                fr = new aFragment();
                break;
            case 1:
                fr = new bFragment();
                break;
        }

        getSupportFragmentManager().beginTransaction()
                .replace(R.id.container, fr)
                .addToBackStack(null)
                .commit();

        Drawer.getInstance().setDrawerChecked(itemId);
        itemPositionStacks.add(itemId);
    }

public void onBackPressed() {
        if(itemPositionStacks.size() > 1) {
            itemPositionStacks.remove(itemPositionStacks.size() - 1);
            Drawer.getInstance().setDrawerChecked(itemIdStacks.get(itemIdStacks.size() - 1));
        }
        super.onBackPressed();
    }
Orientalize answered 17/6, 2016 at 9:8 Comment(0)
G
-2

In your onBackPressed() function .. you must choose which item to be selected by using

drawer.setCheckedItem(R.id.nav_home);

and remove the selection of the another item

drawer.getMenu().findItem(R.id.nav_about).setChecked(false);
Guzman answered 10/5, 2016 at 10:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.