Search code examples
androidnavigation-drawerandroid-architecture-navigation

Back/Up Arrow not working when using navigation drawer


The back or up button is not working when using a navigation drawer. The icon changes from a hamburger (having set the top level destinations) but both open the navigation drawer. I want the back/up arrow to go back in the stack.

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, DrawerLocker {

public static final String TAG = MainActivity.class.getSimpleName();

private DrawerLayout drawerLayout;
private NavigationView navView;
private Toolbar toolbar;

private NavController navController;
private ActionBarDrawerToggle drawerToggle;


private AppBarConfiguration appBarConfiguration;

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

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


    //configure drawer layout
    drawerLayout = findViewById(R.id.drawer_layout);
    navView = findViewById(R.id.drawer_navigation_view);

    navController = Navigation.findNavController(this,R.id.nav_host_fragment);

    appBarConfiguration = new AppBarConfiguration.Builder(R.id.scenarioListFragment,
            R.id.tokenListFragment, R.id.settingsFragment,R.id.historyFragment)
            .setDrawerLayout(drawerLayout)
            .build();

    NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
    NavigationUI.setupWithNavController(navView, navController);

    navView.setNavigationItemSelectedListener(this);

    drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);

    drawerLayout.addDrawerListener(drawerToggle);
    drawerToggle.syncState();

    if (savedInstanceState == null ) {
        navView.setCheckedItem(R.id.drawer_menu_scenario);
        toolbar.setTitle("Scenarios");
    }
}

I watched this video, which made it seem sort of simple, but it is referring to Kotlin and my code is not far off.

This post covers a similar challenge as well, though in Kotlin I tried adding a setNavigationOnClickListener and put a logd statement in it. It never got fired, but the solution itself seemed like it shouldn't be necessary.

This post seems to have cover the same issue but there are no answers. One of the responses says to setupActionBarWithNavController, which I have:

NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);

This function has a lot of overloads and I've tried a number of them, but they seem to cause me to lose the set of top level destinations (hamburger icon for multiple fragments) and undue my the navigation which is working.

I tried to follow this documentation, but it only seemed to step me back from where I was. This call:

    AppBarConfiguration appBarConfiguration =
            new AppBarConfiguration.Builder(navController.getGraph())
                    .setDrawerLayout(drawerLayout)
                    .build();

Seems to replace the topLevelDestinations and use the navController.getGraph(), but since I have multiple ones, I have been referencing the fragments themselves.

I did ask about this problem previously but it was clear to me I did not explain it well (answers addressed how to pop back and not why the back arrow was not working). I would have deleted it but people did answer and the guidance SO provided was that I should not delete it in that case. I am sorry if I caused confusion.


Solution

  • There's two issues:

    1. As per the Add a navigation drawer documentation:

    When using NavigationUI, the top app bar helpers automatically transition between the drawer icon and the Up icon as the current destination changes. You don't need to use ActionBarDrawerToggle.

    So you must remove all of your ActionBarDrawerToggle code.

    1. As per the Setting up the Action bar documentation:

    override onSupportNavigateUp() to handle Up navigation:

    @Override
    public boolean onSupportNavigateUp() {
        NavController navController = Navigation.findNavController(this,
                R.id.nav_host_fragment);
        return NavigationUI.navigateUp(navController, appBarConfiguration)
                || super.onSupportNavigateUp();
    }
    

    Note that your if (savedInstanceState == null) is also unnecessary if you've included an android:label on your destinations and are using setupWithNavController.