Set toolbar title dynamically using navigation-component

you can add a method for updating the fragment title and call it in fragment onStart() method

fun updateToolbarTitle(title: String) {
    supportActionBar?.title = title
}

and remove lable attribute from tag in your nav_graph.xml so it'll be like that

<fragment
    android:id="@+id/myFragment"
    android:name=".MyFragment"/>

In case you are passing a custom Object as parameter, you can use navController.addOnDestinationChangedListener.

navController.addOnDestinationChangedListener(new NavController.OnDestinationChangedListener() {
    @Override
    public void onDestinationChanged(@NonNull NavController controller, @NonNull NavDestination destination, @Nullable Bundle arguments) {
        Log.i(TAG, "onDestinationChanged");
        switch (destination.getId()) {
            case R.id.mainFragment:
                updateToolbarAndBottomNavigation("Main Title", "Main Subtitle", View.VISIBLE);
                break;
            case R.id.shopFragment:
                updateToolbarAndBottomNavigation("custom title", null, View.VISIBLE);
                break;
            case R.id.shopcartFragment:
                StoreEntity store = (StoreEntity) arguments.get("storeEntity");
                Log.i(TAG, "onDestinationChanged: ShopCartFragment args: "+store.getName());
                updateToolbarAndBottomNavigation(store.getName(), null, View.GONE);
                break;
        }

    }
});

private void updateToolbarAndBottomNavigation(String title, String subtitle, int visibility) {
    getSupportActionBar().setTitle(title);
    getSupportActionBar().setSubtitle(subtitle);
    bottomNavigationView.setVisibility(visibility);
}

Where the arguments.get() was retrieved from android:name in the nav_graph.xml.

<fragment
        android:id="@+id/shopcartFragment"
        android:name="com.myapp.ShopcartFragment"
        tools:layout="@layout/fragment_shopcart" >
        <argument
            android:name="storeEntity" // GET ARGUMENTS NAME HERE
            app:argType="com.myapp.LocalDatabase.StoreEntity" />
    </fragment>

I hope it can help more people!


Navigation supports arguments in labels as of Navigation 1.0.0-alpha08 or higher:

Destination labels, when used with NavigationUI methods, will now automatically replace {argName} instances in your android:label with the correct argument b/80267266

Therefore you can set your label to android:label="{dynamicTitle}", then pass in an argument to your navigate call. As you're using Safe Args, you'd want to add an argument to your destination:

<fragment
    android:id="@+id/myFragment"
    android:name=".MyFragment"
    android:label="{dynamicTitle}">
  <argument
      android:name="dynamicTitle"
      app:argType="string"/>
</fragment>

Then pass in your dynamic title when constructing your directions:

val directions = YourDirections.actionToMyFragment(someTitle)
it.findNavController().navigate(directions)

Of course, you can listen for navigation events yourself and use your own OnDestinationChangedListener to do whatever you want, including setting the label to whatever you want. There's no requirement to use NavigationUI and any listener to add after calling the NavigationUI methods will override whatever it sets.