Search code examples
androidkotlinandroid-fragmentsandroid-architecture-navigation

NavigationComponent: NavHostFragment inside a fragment


I have this tabbed UI with a navigation component and a BottomNavigationView that handles the tabs. My use case involves one of these tab fragments to have a BottomNavigationView of its own.

I don't think the nested navigation graphs will work for me because I need there to be an inner NavHostFragment and a second BottomNavigationView.

So I'm in the fragment which I wish to host my inner navigation graph. It contains a fragment like so.

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/inner_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:defaultNavHost="true"

I need a way to get the navigation controller for the above fragment.

Normally when you're in an activity you'd call the findFragmentById from the supportFragmentManager with the id you gave to your fragment.

val navHostFragment = supportFragmentManager.findFragmentById(R.id.outer_nav_host) as NavHostFragment

So I tried to call that on the activity object from within my inner fragment

requireActivity().supportFragmentManager.findFragmentById(R.id.inner_host_fragment)

But the findFragmentById returns null.


Solution

  • Try to get the NavHostFragment from the supportFragmentManager, and then get the navController upon.

    val navHostFragment =
            requireActivity().supportFragmentManager.primaryNavigationFragment as NavHostFragment
    val navController = navHostFragment.navController
    

    Thanks to @ianhanniballake you need to use the childFragmentManager as your current fragment is a child of a fragment.

    So try to use instead:

    val navHostFragment =
        childFragmentManager.primaryNavigationFragment as NavHostFragment
    val navController = navHostFragment.navController
    

    UPDATE:

    throws this java.lang.NullPointerException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment

    So, the solution as from comments:

    val navHostFragment = childFragmentManager.findFragmentById(R.id.nav_host_fragment) 
                           as NavHostFragment 
    

    And replace nav_host_fragment with the id of the inner NavHostFragment.