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.
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