androidkotlinandroid-fragmentsnavgraphandroid-navhostfragment

Navigation issue from a Fragment. Android


I'm facing an issue with Android Navigation Component. I have set up a NavHostFragment in my app, and I'm trying to navigate from one fragment to another using Navigation.findNavController(view).navigate(). However, I keep encountering the error "View does not have a NavController set."

here's the project if you want to take a closer look: https://github.com/giorgishubitidze3/fitnessApp

The bottom menu bar icons, which i have set up in main activity, work perfectly fine. but if i try to navigate from workout fragment to workout details fragment app crashes and gives me the error "View does not have a NavController set."

I have a click listener set up inside the recycler view adapter ( which displays items inside workout fragment) like this:

holder.itemView.setOnClickListener{
            switchToDetailCallback()
        }

And i try to navigate to a different fragment like this:

val adapter = ExerciseAdapter(data){ ->
           Navigation.findNavController(view).navigate(R.id.action_workoutsFragment_to_workoutDetails)
        }

Also here's the part of main activity xml in which i have set up fragment container view:

<androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toTopOf="@+id/bottomNavigationView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/nav_graph"
        app:defaultNavHost="true"/>

Tried changing stuff with the help of chatgpt but still doesn't work.


Solution

  • Hi I have reviewed the code on git The error is happening on the main activity, when using a navigation graph you should not replace fragments in order to navigate. To navigate your top level destinations on the bottom bar you can call bottomNavigationBar.setupWithNavController(navController) This will handle navigation when user taps on bottom navigation item i.e sessions Note: Bottom navigation menu item ids should match fragment ids on your navigation graph for this to work. Your main activity should look like this

     class MainActivity : AppCompatActivity() {
    /*
    initializes the navigation controller lazily
     */
    private val navController: NavController by lazy {
        val navHostFragment = supportFragmentManager
            .findFragmentById(R.id.fragment_container) as NavHostFragment
        navHostFragment.navController
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val bottomNavigationBar = findViewById<BottomNavigationView>(R.id.bottomNavigationView)
        val actionBar: ActionBar? = supportActionBar
        actionBar?.hide()
        /*
            handles top level navigation between fragments
            Note: menu items in bottom_navigation_menu.xml must have the same id as the fragments
        * https://developer.android.com/guide/navigation/navigation-ui#bottom_navigation
         */
        bottomNavigationBar.setupWithNavController(navController)
    
        // hide bottom navigation bar when not on top level destinations
        navController.addOnDestinationChangedListener { _, destination, _ ->
            if (destination.id in listOf(
                    R.id.homeFragment,
                    R.id.sessionFragment,
                    R.id.workoutsFragment,
                    R.id.profileFragment
                )
            ) {
                bottomNavigationBar.visibility = View.VISIBLE
            } else {
                bottomNavigationBar.visibility = View.GONE
            }
        }
    }
    

    }

    Then from workout fragment on the adapter callback you can now just call findNavController().navigate(R.id.action_workoutsFragment_to_workoutDetails) To navigate to workout details.

    refer to https://developer.android.com/guide/navigation/integrations/ui?authuser=1#bottom_navigation