I am using Navigation Component for navigating in my app. It works fine inside fragments but it fails to find the nav host in the activity that holds the actual navigation host.
I am trying to open a new fragment when the user clicks on FAB, which I included in Main activity's XML. When I call findNavController() it fails to find the controller. The nav host controller is in the XML layout. I can't understand why it fails to find it.
MainActivity
class MainActivity : AppCompatActivity(), OnActivityComponentRequest { override fun getTabLayout(): TabLayout { return this.tabLayout } override fun getFap(): FloatingActionButton { return this.floatingActionButton } private lateinit var tabLayout: TabLayout private lateinit var floatingActionButton: FloatingActionButton override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) this.tabLayout = tabs this.floatingActionButton = fab fab.setOnClickListener { it.findNavController().navigate(R.id.addNewWorkoutFragment) } } }
Activity main XML
<?xml version="1.0" encoding="utf-8"?> <androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_width="match_parent" android:layout_height="match_parent" tools:context=".domain.MainActivity" android:animateLayoutChanges="true"> <com.google.android.material.appbar.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay"/> <com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.google.android.material.tabs.TabItem android:text="Test 1" android:layout_height="match_parent" android:layout_width="match_parent"/> <com.google.android.material.tabs.TabItem android:text="Test 2" android:layout_height="match_parent" android:layout_width="match_parent"/> </com.google.android.material.tabs.TabLayout> </com.google.android.material.appbar.AppBarLayout> <fragment android:id="@+id/nav_host_fragment" android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" app:defaultNavHost="true" app:navGraph="@navigation/main_navigation" /> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="bottom"/> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_anchorGravity="right|top" app:layout_anchor="@+id/bar" android:src="@drawable/ic_add_black_24dp"/> </androidx.coordinatorlayout.widget.CoordinatorLayout>
NavController manages app navigation within a NavHost . Apps will generally obtain a controller directly from a host, or by using one of the utility methods on the Navigation class rather than create a controller directly. Navigation flows and destinations are determined by the navigation graph owned by the controller.
In the Project window, right-click on the res directory and select New > Android Resource File. The New Resource File dialog appears. Type a name in the File name field, such as "nav_graph". Select Navigation from the Resource type drop-down list, and then click OK.
When navigating back to destination A, we also popUpTo A, which means that we remove B and C from the stack while navigating. With app:popUpToInclusive="true" , we also pop that first A off of the stack, effectively clearing it.
I was getting the same exeception until I managed to get the navController this way:
val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_fragment_container_view_id) as NavHostFragment val navController = navHostFragment.navController
Obtained from this answer:
Before finding the nav controller, you need to set the view, if you are using binding:
binding = BaseLayoutBinding.inflate(layoutInflater) val view = binding.root setContentView(view)
If not:
setContentView(R.layout.activity_main)
Use the corresponding binding for fragments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With