How does one pass argument(s) to a nested Navigation architecture component graph?
Let's say I construct my navigation graph to navigate from FragmentA --> Nested
, where Nested
contains FragmentB --> FragmentC
...
If this was a pure FragmentA --> FragmentB...
graph, I would just set up the navigation with FragmentADirections.actionFragmentAToFragmentB(argument = foo)
. But that action takes zero arguments as soon as you turn B --> C
into Nested
...
So what am I supposed to do?
Global actions might be a way but I didn't get that working as I wanted once I extracted the nested graph to its own .xml
. But it turned out to be embarrassing simple - just add the arguments manually in code, to your action.
An example related to the question would be:
Save the nested graph to nested_graph.xml
, it will look something like
<navigation
android:id="@+id/nested_graph"
app:startDestination="@id/fragmentB"
...>
<fragment
android:id="@+id/fragmentB"
...>
<argument
android:name="foo"
app:argType="integer"/>
<action
... // navigation action to FragmentC />
</fragment>
<fragment ... // FragmentC stuff
</navigation>
To pass arguments to nested_graph.xml
from a different graph, say root_graph.xml
do
<navigation
android:id="@+id/root_graph"
app:startDestination="@id/fragmentA"
...>
<fragment
android:id="@+id/fragmentA"
... >
<action
android:id="@+id/action_fragmentA_to_nested_graph"
app:destination="@id/nested_graph">
<argument
android:name="foo"
app:argType="integer"/>
</action>
</fragment>
<include app:graph="@navigation/nested_graph"/>
</navigation>
In other words, just add the same <argument ... />
to the root_graph
action as you expect to receive in the nested_graph
.
Use global actions for that like below and pass arguments.
<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/mainFragment">
<activity android:id="@+id/playbackActivity"
android:name="com.cinderellaman.general.ui.activities.PlaybackActivity"
android:label="activity_playback"
tools:layout="@layout/activity_playback">
<argument android:name="videoId"
app:nullable="true"/>
<argument android:name="position"
app:argType="integer"
android:defaultValue="1"/>
</activity>
<action android:id="@+id/action_global_playbackActivity"
app:destination="@id/playbackActivity"/></navigation>
actully it's very simple you just need to add your arguments in nested_nav for example
<navigation
android:id="@+id/root_graph"
app:startDestination="@id/fragmentA"
...>
<fragment
android:id="@+id/fragmentA"
... >
<action
android:id="@+id/action_fragmentA_to_nested_graph"
app:destination="@id/nested_graph">
</action>
</fragment>
<navigation
android:id="@+id/nested_graph"
app:startDestination="@id/fragmentB"
...>
<argument
android:name="foo"
app:argType="integer"/>
<fragment
android:id="@+id/fragmentB"
...>
<argument
android:name="foo"
app:argType="integer"/>
<action
... // navigation action to FragmentC />
</fragment>
<fragment ... // FragmentC stuff
</navigation>
</navigation>
or you can send your data with a bundle
To resolve this issue you need to do the following:
Included Graph
in the <navigation>
block add the destination to the @id/included_fragment
:<action
android:id="@+id/open_included_fragment"
app:destination="@id/included_fragment"/>
Main Graph
make sure that your desired <action>
id is the same as the id of the <action>
in Included Graph
, in your case it should remain the same. Also, to validate the destination (as below), you can remove the +
sign from the <action>
id in Main Graph
, because in this case, it should be using the id of the <action>
from the Included Graph
.
Overall your code should be like this:
Main Graph
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_graph"
app:startDestination="@id/main_fragment">
<fragment
android:id="@+id/main_fragment"
android:name="com......MainFragment">
<action
android:id="@id/open_included_fragment"
app:destination="@id/included_graph"/>
</fragment>
<include app:graph="@navigation/included_graph"/>
</navigation>
Included Graph
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/included_graph"
app:startDestination="@id/included_fragment">
<action
android:id="@+id/open_included_fragment"
app:destination="@id/included_fragment"/>
<fragment
android:id="@+id/included_fragment"
android:name="com......IncludedFragment">
<argument
android:name="some_argument"
app:argType="integer" />
</fragment>
</navigation>
If you do not want to create a separated xml for the nested graph you can override destination argument in an action as android developers says here . I just test it for use with navigation graph view model scope and it worked perfectly. I am using Version 2.2.0-alpha03 of navigation component. After added those params to the action action_inboxFragment_to_conversation_graph , now the InboxFragmentDirections.ActionInboxFragmentToConversationGraph is generated correctly.
<?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/messages_graph"
app:startDestination="@id/inboxFragment">
<fragment
android:id="@+id/inboxFragment"
android:name="com.wlpr.docfinder.ui.fragment.InboxFragment"
android:label="fragment_inbox"
tools:layout="@layout/fragment_inbox" >
<action
android:id="@+id/action_inboxFragment_to_conversation_graph"
app:destination="@id/conversation_graph">
<argument
android:name="participantName"
android:defaultValue="Conversation"
app:argType="string"
app:nullable="true" />
<argument
android:name="documentsCount"
android:defaultValue="1"
app:argType="integer" />
</action>
</fragment>
<navigation
android:id="@+id/conversation_graph"
android:label="conversationGraph"
app:startDestination="@id/conversationFragment">
<fragment
android:id="@+id/conversationFragment"
android:name="com.wlpr.docfinder.ui.fragment.ConversationFragment"
android:label="fragment_conversation"
tools:layout="@layout/fragment_conversation">
<action
android:id="@+id/action_conversationFragment_to_reportingDetailsFragment"
app:destination="@id/reportingDetailsFragment" />
<argument
android:name="participantName"
android:defaultValue="Conversation"
app:argType="string"
app:nullable="true" />
<argument
android:name="documentsCount"
android:defaultValue="1"
app:argType="integer" />
</fragment>
<!-------- more fragments... -------->
</navigation>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.