Is there any way to navigate to a certain fragment from another dynamic module and not navigate to the start destination? If not, what are the alternatives?
<fragment
android:id="#+id/loginFragment"
android:name="com.example.feature.login.presentation.LoginFragment"
android:label="LoginFragment">
<action
android:id="#+id/actionLoginToHome"
app:destination="#id/featureHomeNavGraph" />
</fragment>
<include-dynamic
android:id="#+id/featureHomeNavGraph"
app:graphResName="feature_home_nav_graph"
app:moduleName="feature_home" />
While this code works fine, it navigates me to the start destination but I need to navigate to another one.
Solution 1: Navigate to specific fragment and do not use <include-dynamic>
<fragment
android:id="#+id/profileDetailsFragment"
android:name="com.example.feature.profiles.presentation.details.ProfileDetailsFragment"
android:label="Profile Details"
app:moduleName="feature_profiles" />
Solution 2: Create a new graph XML with different start destination.
A good way to do this for embedded nav graphs is to have a blank Navigation Fragment. You get your action to go to this fragment and then send it arguments on where to navigate next. Some sample code:
class NavigatorFragment : Fragment() {
companion object {
const val REQUEST_PAGE_NAME = "REQUEST_PAGE_NAME"
const val PAGE_TYPE_ACTIVATE_CARD = "PAGE_TYPE_ACTIVATE_CARD"
const val PAGE_TYPE_CREDIT_LIMIT = "PAGE_TYPE_CREDIT_LIMIT"
const val PAGE_TYPE_SCC_HUB = "PAGE_TYPE_SCC_HUB"
const val PAGE_TYPE_ABOUT_CARD = "about_card"
const val PAGE_TYPE_MAKE_PAYMENT = "PAGE_TYPE_MAKE_PAYMENT"
fun createBundle(pageName: String) =
Bundle().apply {
putString(REQUEST_PAGE_NAME, pageName)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
when (arguments?.getString(REQUEST_PAGE_NAME)) {
PAGE_TYPE_ACTIVATE_CARD ->
findNavController().navigate(R.id.to_activateSecuredCard)
PAGE_TYPE_CREDIT_LIMIT ->
findNavController().navigate(R.id.to_creditLimit)
PAGE_TYPE_ABOUT_CARD ->
findNavController().navigate(R.id.to_aboutSecuredCard, arguments)
PAGE_TYPE_SCC_HUB ->
findNavController().navigate(R.id.to_sccHub)
PAGE_TYPE_MAKE_PAYMENT ->
findNavController().navigate(R.id.to_sccMakePayment)
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val binding: FragmentSecuredCardNavigatorBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_secured_card_navigator, container, false)
binding.lifecycleOwner = viewLifecycleOwner
if (findNavController()
.currentDestination.toString()
.contains(this.javaClass.name)
){
findNavController().popBackStack()
}
return binding.root
}
}
main navigation:
<?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"
app:startDestination="#+id/home_dashboard_fragment">
<include app:graph="#navigation/nav_graph_secured_card" />
<!-- rest of navigation graph-->
.....
</navigation>
secured card navigation:
<?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_root_secured_card"
app:startDestination="#id/securedCardNavigator">
<fragment
android:id="#+id/securedCardNavigator"
android:name="com.greendotcorp.securedcard.fragment.NavigatorFragment">
<action
android:id="#+id/to_activateSecuredCard"
app:destination="#+id/activateSecuredCard"
app:popUpTo="#+id/securedCardNavigator"
app:popUpToInclusive="true" />
</fragment>
</navigation>
Navigating to secured card navigation:
findNavController().navigate(R.id.nav_root_secured_card, NavigatorFragment.createBundle(NavigatorFragment.PAGE_TYPE_SCC_HUB))
Related
I am new to using the navigation component for Android. Most of the examples I have seen online discuss fragment navigation within an activity but, in my case, I want to navigate within a base fragment. In the picture below, I would like to navigate from a login fragment to a signup fragment within the same settings tab but am running into issues and have tried various possible solutions. Any help would be appreciated as I am aware that I can certainly missing something.
java.lang.IllegalArgumentException: Navigation action/destination com.example.animaljournalapp:id/action_userAccountFragment_to_userSignUpFragment cannot be found from the current destination Destination(com.example.animaljournalapp:id/navigation_settings) label=Settings class=com.example.animaljournalapp.ui.settings.UserAccountFragment
I attempt to perform the navigation in the login fragment file through a listener I have attached to a "Sign Up" button:
UserAccountFragment.kt
class UserAccountFragment : Fragment() {
private lateinit var userAccountModel: UserAccountModel
private lateinit var navHostFrag: Fragment
private var _binding: FragmentUserAccountBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
userAccountModel =
ViewModelProvider(this).get(UserAccountModel::class.java)
navHostFrag = SettingsMainFragment()
_binding = FragmentUserAccountBinding.inflate(inflater, container, false)
val root: View = binding.root
val loginButton: Button = root.findViewById(R.id.login_button)
val signupButton: Button = root.findViewById(R.id.signup_button)
loginButton.setOnClickListener{ view: View ->
Toast.makeText(this.context, "Hi", Toast.LENGTH_LONG).show()
}
signupButton.setOnClickListener { view: View ->
val action = UserAccountFragmentDirections.actionUserAccountFragmentToUserSignUpFragment()
Navigation.findNavController(view).navigate(action)
}
return root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
The main activity has a navigation graph of the following:
mobile_navigation.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/mobile_navigation"
app:startDestination="#+id/navigation_home">
<fragment
android:id="#+id/navigation_home"
android:name="com.example.animaljournalapp.ui.home.HomeFragment"
android:label="#string/title_home"
tools:layout="#layout/fragment_home" />
<fragment
android:id="#+id/navigation_dashboard"
android:name="com.example.animaljournalapp.ui.dashboard.DashboardFragment"
android:label="#string/title_dashboard"
tools:layout="#layout/fragment_dashboard" />
<fragment
android:id="#+id/navigation_settings"
android:name="com.example.animaljournalapp.ui.settings.UserAccountFragment"
android:label="#string/title_settings"
tools:layout="#layout/fragment_settings_main" />
</navigation>
settings_navigation.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/settings_navigation"
app:startDestination="#id/userAccountFragment">
<fragment
android:id="#+id/userAccountFragment"
android:name="com.example.animaljournalapp.ui.settings.UserAccountFragment"
android:label="fragment_user_account"
tools:layout="#layout/fragment_user_account" >
<action
android:id="#+id/action_userAccountFragment_to_userSignUpFragment"
app:destination="#id/userSignUpFragment" />
</fragment>
<fragment
android:id="#+id/userSignUpFragment"
android:name="com.example.animaljournalapp.ui.settings.UserSignUpFragment"
android:label="UserSignUpFragment" />
</navigation>
fragment_settings_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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=".ui.settings.SettingsMainFragment">
<fragment
android:id="#+id/settings_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/settings_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>
I'm using Navigation Component with Kotlin, and have three main tabs in nav_dashboard - Explore, My Groups and Profile. When I start application the startDestination is nav_explore, but then I want to go from there to different screens eg. CreateGroupFragment/nav_create_group and from there I have button that I want to redirect me to nav_dashboard but with My Groups selected - I guess that then the startDestination needs to be nav_profile. But how I can I implement that?
Dashboard Fragment (it contains Fragment Container View in XML):
internal class DashboardFragment : Fragment() {
lateinit var navigator: DashboardNavigator
private var _binding: FragmentDashboardBinding? = null
private val binding
get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentDashboardBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initBottomNavigation()
}
private fun initBottomNavigation() {
with(binding.bottomNavigationView) {
setupWithNavController(getDashboardNestedNavController())
}
}
private fun getDashboardNestedNavController(): NavController {
val navHostFragment = childFragmentManager.findFragmentById(R.id.nav_host_container) as NavHostFragment
val navGraph = navHostFragment.navController.navInflater.inflate(R.navigation.nav_dashboard_menu)
navHostFragment.navController.addOnDestinationChangedListener { _, destination, bundle ->
when (destination.id) {
R.id.exploreFragment, R.id.myGroupsFragment, R.id.profileFragment -> setBottomNavVisibility(View.VISIBLE)
else -> setBottomNavVisibility(View.GONE)
}
}
return navHostFragment.navController
}
private fun setBottomNavVisibility(visibility: Int) {
binding.bottomNavigationView.visibility = visibility
}
}
nav_dashboard:
<?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"
android:id="#+id/nav_dashboard_menu"
app:startDestination="#id/nav_explore">
<include app:graph="#navigation/nav_explore" />
<include app:graph="#navigation/nav_my_groups" />
<include app:graph="#navigation/nav_profile" />
</navigation>
nav_create_group:
<?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_create_group"
app:startDestination="#id/createGroupFragment">
<include app:graph="#navigation/nav_create_group_map" />
<include app:graph="#navigation/nav_my_groups" />
<fragment
android:id="#+id/createGroupFragment"
android:name="com.wojciechkula.locals.presentation.creategroup.CreateGroupFragment"
android:label="#string/create_group_create_group"
tools:layout="#layout/fragment_create_group">
<action
android:id="#+id/openMap"
app:destination="#id/nav_create_group_map" />
<!-- Here I want another action to navigate to nav_dashboard with startDestination: nav_my_groups-->
</fragment>
</navigation>
First of all, you don't need to change the startDestination.
Secondly, why are you using multiple graphs? That usually makes things more complicated!
Anyway, you can just set the selected tab manually.
binding.bottomNavigationView.menu.findItem(R.id.tabId).isChecked = true
"tabId" is the id of the item in your bottom nav xml file.
I'm trying to update my app to use BottomNavigationView. The first tab contains a HostFragment with a loading spinner that performs a network request to determine which fragment, either HomeFragment or LockedFragment, should be shown in that tab.
MainActivity handles the initial setup of the BottomNavigationView:
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)
appBarConfiguration = AppBarConfiguration(
setOf(R.id.mainFragment)
)
setupActionBarWithNavController(navController, appBarConfiguration)
}
My main nav graph looks like this:
<?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"
android:id="#+id/nav_graph"
app:startDestination="#+id/home">
<include app:graph="#navigation/home"/>
<include app:graph="#navigation/list"/>
<include app:graph="#navigation/form"/>
</navigation>
with the home graph looking like:
<?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"
android:id="#+id/home"
app:startDestination="#+id/hostFragment">
<fragment
android:id="#+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="#+id/action_hostFragment_to_homeFragment"
app:destination="#id/homeFragment" />
<action
android:id="#+id/action_hostFragment_to_lockedFragment"
app:destination="#id/lockedFragment" />
</fragment>
<fragment
android:id="#+id/homeFragment"
android:name="com.example.android.bottomnav.homescreen.HomeFragment"
android:label="Home" />
<fragment
android:id="#+id/lockedFragment"
android:name="com.example.android.bottomnav.homescreen.LockedFragment"
android:label="Locked"/>
</navigation>
HostFragment get's shown fine and loads it's data:
class HostFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_host, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
determineFragmentToShow()
}
private fun determineFragmentToShow() {
lifecycleScope.launchWhenStarted {
// mock network call to determine tab
delay(1500)
// show HomeFragment for the sake of the example, but note that
// this would be dependent on the network call's result above
findNavController().navigate(R.id.action_hostFragment_to_homeFragment)
}
}
}
which successfully navigates us to HomeFragment.
Now the problem is that whenever I press the back button from HomeFragment it goes back to HostFragment instead of closing the app.You can see the behavior in this video here.
I tried to set the popUpTo and popUpInclusive tags inside of home.xml like this:
<fragment
android:id="#+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="#+id/action_hostFragment_to_homeFragment"
app:destination="#id/homeFragment"
app:popUpTo="#id/home"
app:popUpToInclusive="true"/>
<action
android:id="#+id/action_hostFragment_to_lockedFragment"
app:destination="#id/lockedFragment"
app:popUpTo="#id/home"
app:popUpToInclusive="true"/>
</fragment>
That got the app to close when pressing back from HomeFragment, but now each time I switch to a new tab, it creates a new instance of the fragment and adds it to the backstack. Pressing the back button then will traverse them all backwards. You can see that behavior in this video here.
So how can I update the start destination of a nested navigation graph?
I'm using the latest 2.4.0-alpha10 of navigation component so that I can get native support for multiple backstacks. Any help is greatly appreciated!
I was able to utilize the answer here to get a solution working for me.
Inside of determineFragmentToShow() in HostFragment, I just replaced findNavController().navigate(R.id.action_hostFragment_to_homeFragment) with
val navController = findNavController()
val graph = navController.graph
val walletGraph = graph.findNode(R.id.home) as NavGraph
walletGraph.setStartDestination(R.id.homeFragment)
navController.navigate(R.id.action_hostFragment_to_homeFragment)
I still needed to include the popUpTo and popUpInclusive tags here
<fragment
android:id="#+id/hostFragment"
android:name="com.example.android.bottomnav.homescreen.HostFragment"
android:label="Host">
<action
android:id="#+id/action_hostFragment_to_homeFragment"
app:destination="#id/homeFragment"
app:popUpTo="#id/home"
app:popUpToInclusive="true"/>
<action
android:id="#+id/action_hostFragment_to_lockedFragment"
app:destination="#id/lockedFragment"
app:popUpTo="#id/home"
app:popUpToInclusive="true"/>
</fragment>
but this got me the back behavior I was looking for!
I cannot understand what is the reason for the error java.lang.NullPointerException: null cannot be cast to non-null type androidx.navigation.fragment.NavHostFragment
This is my host fragment:
class HostFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.fragment_host, container, false)
// error here
val navHostFragment = requireActivity().supportFragmentManager.findFragmentById(R.id.hostFragment) as NavHostFragment
//
val navController = navHostFragment.navController
root.host_text_view.setOnClickListener {
Log.d("Tag", "clicked")
navController.navigate(R.id.action_hostFragment_to_secondFragment)
}
return root
}
}
I want to navigate to SecondFragment by clicking on the textView. And back.
And nav graph .xml file:
<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/hostFragment">
<fragment
android:id="#+id/hostFragment"
android:name="com.example.test.HostFragment"
android:label="fragment_host"
tools:layout="#layout/fragment_host" >
<action
android:id="#+id/action_hostFragment_to_secondFragment"
app:destination="#id/secondFragment" />
</fragment>
<fragment
android:id="#+id/secondFragment"
android:name="com.example.test.SecondFragment"
android:label="fragment_second"
tools:layout="#layout/fragment_second" >
<action
android:id="#+id/action_secondFragment_to_hostFragment"
app:destination="#id/hostFragment" />
</fragment>
</navigation>
The Navigation graph has its final form like:
best way to use Navigation Graph is after the view is created, since some view takes time to create so u might get this exception as your view is still in processing or creating the view.
so to avoid this , u can use OnViewCreated() as
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = Navigation.findNavController(view)
view.imgNumbrLookUp.setOnClickListener {
navController.navigate(R.id.action_homeFragment_to_webActivity)
}
}
You don't need to find your navHostFragment to navigate
val root = inflater.inflate(R.layout.fragment_host, container, false)
root.host_text_view.setOnClickListener {
Log.d("Tag", "clicked")
if (findNavController().currentDestination?.id == hostFragment)
findNavController().navigate(R.id.action_hostFragment_to_secondFragment)
}
You can check for Kotlin methods to navigate
https://developer.android.com/guide/navigation/navigation-navigate
When i navigate to the Tab fragment(having tablayout with viewpager)
I need to nest the tablayout fragments navigation graph with the main navigation graph.
Here is the code.
Main_Navigation_Graph
<?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/C_nav_graph"
app:startDestination="#id/C1_fragment">
<include app:graph="#navigation/tab_navigation" />
<fragment
android:id="#+id/C1_fragment"
android:name="com.example.nestednavigationgraphexample.Fragment_C1"
android:label="C1"
tools:layout="#layout/fragment_c1">
<action
android:id="#+id/C1_to_C2_fragment"
app:destination="#id/C2_fragment" />
</fragment>
<fragment
android:id="#+id/C2_fragment"
android:name="com.example.nestednavigationgraphexample.Fragment_C2"
android:label="C2"
tools:layout="#layout/fragment_c2" >
<action
android:id="#+id/action_C2_fragment_to_tabFragment"
app:destination="#id/tabFragment" />
</fragment>
<fragment
android:id="#+id/tabFragment"
android:name="com.example.nestednavigationgraphexample.Tab_Fragment"
android:label="tabFragment" />
</navigation>
Tab_Navigation_Graph
<?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/tab_navigation"
app:startDestination="#id/cardFragment">
<fragment
android:id="#+id/cardFragment"
android:name="com.example.nestednavigationgraphexample.CardFragment"
android:label="CardFragment" >
<action
android:id="#+id/action_cardFragment_to_fragment_Tab_Sub"
app:destination="#id/fragment_Tab_Sub" />
</fragment>
<fragment
android:id="#+id/fragment_Tab_Sub"
android:name="com.example.nestednavigationgraphexample.Fragment_Tab_Sub"
android:label="fragment_fragment__tab__sub"
tools:layout="#layout/fragment_fragment__tab__sub" />
</navigation>
CardFragment
class CardFragment : Fragment(),View.OnClickListener {
private var counter: Int? = null
var navController: NavController?=null
private val COLOR_MAP = intArrayOf(
R.color.red_100, R.color.red_300, R.color.red_500, R.color.red_700, R.color.blue_100,
R.color.blue_300, R.color.blue_500, R.color.blue_700, R.color.green_100, R.color.green_300,
R.color.green_500, R.color.green_700
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments != null) {
counter = arguments!!.getInt(ARG_COUNT)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? { // Inflate the layout for this fragment
return inflater.inflate(R.layout.card_fragment, container, false)
}
override fun onViewCreated(
view: View,
savedInstanceState: Bundle?
) {
super.onViewCreated(view, savedInstanceState)
view.setBackgroundColor(ContextCompat.getColor(context!!, COLOR_MAP[counter!!]))
val textViewCounter = view.findViewById<TextView>(R.id.tv_counter)
textViewCounter.text = "Fragment No " + (counter!! + 1)
view.findViewById<Button>(R.id.button).setOnClickListener(this)
navController= Navigation.findNavController(activity!!,R.id.nav_host_fragment)
}
companion object {
private const val ARG_COUNT = "param1"
fun newInstance(counter: Int?): CardFragment {
val fragment = CardFragment()
val args = Bundle()
args.putInt(ARG_COUNT, counter!!)
fragment.arguments = args
return fragment
}
}
override fun onClick(v: View) {
when(v!!.id){
R.id.button->
navController!!.navigate(R.id.action_cardFragment_to_fragment_Tab_Sub)
}
}
}
I get the following crash when clicking on button in card Fragment
java.lang.IllegalArgumentException: navigation destination com.example.nestednavigationgraphexample:id/action_cardFragment_to_fragment_Tab_Sub is unknown to this NavController
My tab layout has 2 instances of CardFragment. I am missing on how to nest the two graphs. Please help me with the solution or if someone can refer a good working example, i would be grateful. Thanking in advance.
It would be nice to get the error logcat but I think you haven't provided the action from TabFragment. Here is the action required to include in your tabFragment like this code:
<fragment
android:id="#+id/tabFragment"
android:name="com.example.nestednavigationgraphexample.Tab_Fragment"
android:label="tabFragment">
<action
android:id="#+id/action_cardFragment_to_fragment_Tab_Sub"
app:destination="#id/tabSubFragment" />
</fragment>
<fragment
android:id="#+id/tabSubFragment"
android:name="com.example.nestednavigationgraphexample.Fragment_Tab_Sub"
tools:layout="#layout/fragment_fragment__tab__sub"
android:label="tabSubFragment" />