I am currently implementing the Navigation Component into my app but it seems finding the NavHostFragment just doesn't work no matter what I do.
I have tried, rebuilding, invalidating, and restarting, changing the names around, and updating my Android Studio but nothing seems to work. I think this is also the reason why I get an error when trying to get the NavController in my MainActivity.kt file as it returns null.
Android Studio version 4.0.1
nav_graph.xml image:
nav_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="com.example.movieapp.ui.main.MainFragment"
android:label="MainFragment">
<action
android:id="@+id/action_mainFragment_to_searchMovieFragment"
app:destination="@id/searchMovieFragment" />
</fragment>
<fragment
android:id="@+id/searchMovieFragment"
android:name="com.example.movieapp.ui.search.SearchMovieFragment"
android:label="SearchMovieFragment" />
</navigation>
main_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<include
layout="@layout/appbar" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var toolbar: Toolbar
private val navController by lazy {
(supportFragmentManager.findFragmentById(R.id.main_fragment) as NavHostFragment).navController
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
toolbar = findViewById(R.id.mainToolBar)
setSupportActionBar(toolbar)
setupActionBarWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.main_menu_bar, menu)
return true
}
}
build.gradle (:app)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.app"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {}
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
dataBinding {
enabled true
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
// Retrofit Libraries
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
// Picasso Library
implementation 'com.squareup.picasso:picasso:2.71828'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// Navigation libraries
def nav_version = "2.3.0"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
}
Initally we dont have NavHostFragments. You pointed each fragment to each other, created movement actions but you need something to host this movement. That is where navigation host fragment comes into play. it is NavHostFragment that sort of swaps in our fragments as necessary inside a given layout. So what layout should hold this nav fragment. it is the layout that gets inflated during the main activity. So open activity_main.xml.
You should add Containers/NavHostFragment
When you choose NavHostFragment to drag, you will see the available host fragments.
we should make sure to write this line
android:name="androidx.navigation.fragment.NavHostFragment"
<androidx.fragment.app.FragmentContainerView
android:id="@+id/navController"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="@navigation/nav_graph" />
For me I added android:name="androidx.navigation.fragment.NavHostFragment" inside FragmentContainerView and worked with me
The way I was able to resolve the issue was by going to the Activity.xml and changing the fragment class/component tag from androidx.fragment.app.FragmentContainerView to just fragment. It then showed up in the hosts panel of the navigation graph.
As mentioned in Doc, You can also use the Layout Editor to add a NavHostFragment.
YOU MAY NEED TO RESTART THE ANDROID STUDIO AFTER THIS (not mentioned in the doc)
Also, you may see "fragment" instead of "FragmentContainerView" when you try to add fragment using above method.
I had the same issue and I solved this by creating the NavHostFragment from the Design, Palette and then assign the respective navigation resource file.
You can find NavController in activity as:
class MainActivity : AppCompatActivity() {
private lateinit var toolbar: Toolbar
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main_activity)
toolbar = findViewById(R.id.mainToolBar)
setSupportActionBar(toolbar)
navController = findNavController(R.id.nav_host_fragment)
setupActionBarWithNavController(navController)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.main_menu_bar, menu)
return true
}
}
private val navController by lazy {
(supportFragmentManager.findFragmentById(R.id.main_fragment) as NavHostFragment).navController
}
Your navController is null because I think supportFragmentManager.findFragmentById(R.id.main_fragment) returns null. The id of your navHost is R.id.nav_host_fragment according to your activity layout.