14

I tried to use a global action using Safe Args with nested graphs but I got an error.

FragmentA.kt:

class FragmentA : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_a, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        btFragmentB.setOnClickListener {
            NavHostFragment.findNavController(this)
                .navigate(FragmentBDirections.actionGlobalFragmentB())
        }
    }
}

FragmentB.kt:

class FragmentB : Fragment()

main.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"
    android:id="@+id/main_nav_graph"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.cookpad.arcshowcase.stack.FragmentA"
        android:label="FragmentA" />

    <include app:graph="@navigation/fragment_b" />
</navigation>

fragment_b.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"
    android:id="@+id/fragment_b"
    app:startDestination="@id/fragmentB">
    <fragment
        android:id="@+id/fragmentB"
        android:name="com.cookpad.arcshowcase.stack.FragmentB"
        android:label="FragmentB" />
    <action
        android:id="@+id/action_global_fragmentB"
        app:destination="@id/fragmentB" />
</navigation>

When I run this, I get this error: java.lang.IllegalArgumentException: navigation destination com.cookpad.arc:id/action_global_fragmentB is unknown to this NavController Which seems to indicate that the action_global_fragmentB was never merged from the sub-graph.

Is there a way to use global actions declared inside a nested graph from the outer graph?

Víctor Albertos
  • 8,093
  • 5
  • 43
  • 71

1 Answers1

1

You just need to move your global action to the main graph nav

main.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_nav_graph"
    app:startDestination="@id/fragmentA">

    <fragment
        android:id="@+id/fragmentA"
        android:name="com.cookpad.arcshowcase.stack.FragmentA"
        android:label="FragmentA" />

    <include app:graph="@navigation/fragment_b" />

    <action
            android:id="@+id/action_global_fragmentB"
            app:destination="@id/fragment_b" />
        
</navigation>

fragment_b.xml

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/fragment_b"
    app:startDestination="@id/fragmentB">

    <fragment
        android:id="@+id/fragmentB"
        android:name="com.cookpad.arcshowcase.stack.FragmentB"
        android:label="FragmentB" /> 

</navigation>

FragmentA.kt

class FragmentA : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_a, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        btFragmentB.setOnClickListener {
            NavHostFragment.findNavController(this)
                .navigate(FragmentADirections.actionGlobalFragmentB())
        }
    }
}
Alaa AbuZarifa
  • 1,171
  • 20
  • 39