'Programatically navigating to a fragment used in DrawerLayout

I have followed the guide and setup a basic navigation and drawer layout. I want to be able to navigate to one of the menu items when the user presses a button in the 'home' fragment and also send along a bundle to use in that fragment. Below is my simplified code: drawer menu:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:showIn="navigation_view">

<group android:checkableBehavior="single">
    <item
        android:id="@+id/nav_home"
        android:icon="@drawable/ic_home"
        android:title="@string/home" />
    <item
        android:id="@+id/nav_calendar"
        android:icon="@drawable/ic_calendar_thin"
        android:title="@string/calendar" />
</group>

Navigation:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mobile_navigation"
app:startDestination="@+id/nav_home">

<fragment
    android:id="@+id/nav_home"
    android:name="test.fragment.home.HomeFragment"
    android:label=""
    tools:layout="@layout/fragment_home" >
</fragment>

<fragment
    android:id="@+id/nav_calendar"
    android:name="test.fragment.home.CalendarFragment"
    android:label=""
    tools:layout="@layout/fragment_calendar" />

And then setup in activity:

    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_calendar)
            .setOpenableLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.fragment_container);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

I have 2 buttons in home fragment. If the user presses them, I want to send a Bundle to that fragment saying with argument "show" = "today" or "show"="week". If the user selects the calendar directly from the drawer menu, I want no bundle values.

I have tried:

NavHostFragment.findNavController(HomeFragment.this).navigate(R.id.nav_calendar, bundle);

Which seems to work fine at first. But then if I select Home from the drawer menu, it doesn't navigate anywhere. So I went to go look what the code does if you select a Drawer menu item and did this instead:

    NavOptions.Builder builder = new NavOptions.Builder();
    builder.setLaunchSingleTop(true);
    builder.setRestoreState(false);
    builder.setPopUpTo(navController.getGraph().getStartDestinationId(), false, true);

    builder.setEnterAnim(androidx.navigation.ui.R.animator.nav_default_enter_anim)
            .setExitAnim(androidx.navigation.ui.R.animator.nav_default_exit_anim)
            .setPopEnterAnim(androidx.navigation.ui.R.animator.nav_default_pop_enter_anim)
            .setPopExitAnim(androidx.navigation.ui.R.animator.nav_default_exit_anim);
    navController.navigate(R.id.nav_calendar, bundle, builder.build());

Which seems mostly to work, except if I use the button before I navigate via the drawer menu - then the new bundle never comes through and I keep getting the same bundle as triggered by the button. I feel like this should be basic functionality and I am really just missing something?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source