architecture-components-samples icon indicating copy to clipboard operation
architecture-components-samples copied to clipboard

Use same fragment multiple times in different navigation graph

Open Motazlubbad opened this issue 4 years ago • 11 comments

I would like to navigate to fragment A in more than one graph.

"Now I get this error : navigation destination action_compareListFragment_to_productPageFragment is unknown to this NavController"

How should I handle this situation?

Motazlubbad avatar Nov 26 '19 06:11 Motazlubbad

Having the same issue. Any solution?

Rissmon avatar Dec 08 '19 18:12 Rissmon

always!! i was also facing that problem. I hope this can help you. check the current destination id like for example if (findNavController().currentDestination?.id == R.id.currentfragmentname) { findNavController().navigate(R.id.action_currentfragmentname_to_anyfragmentname) }

DJDrama avatar Dec 16 '19 08:12 DJDrama

+1 I'm having this problem too with jetpack navigation v.2.1.0

@DJDrama can you share the complete snippet of it?

handhikadj avatar Jan 01 '20 09:01 handhikadj

Just use nested navigation.

Put the fragment in different navigation file and add it as nested navigation in other file.

inromualdo avatar Jan 12 '20 11:01 inromualdo

You Just have set destination id same as your fragment id.

Like below

<fragment
        android:id="@+id/externalProfileFragment"
        android:name="com.social.footprint.ui.external_user_profile.ExternalProfileFragment"
        android:label="ExternalProfileFragment"
        tools:layout="@layout/external_profile_fragment">
        <argument
            android:name="user_id"
            app:argType="string" />
        <action
            android:id="@+id/action_externalProfileFragment_to_externalProfileFragment"
            app:destination="@id/externalProfileFragment" />


</fragment>

pankajjangid avatar Apr 08 '20 09:04 pankajjangid

I want to do the same but I think this is not possible:

The nested graph encapsulates its destinations. As with a root graph, a nested graph must have a destination identified as the start destination. Destinations outside of the nested graph, such as those on the root graph, access the nested graph only through its start destination.

Taken from: Nested Navigation Graphs

So basically you can only have an action that will navigate to the "start destination" of a nested graph. No way to access an inner fragment/destination inside a nested graph. I think the solution is NOT to use nested graphs whenever you want to "share" a fragment/destination across multiple graphs.

UPDATE: I had to split the "nested graph" that contained the fragment that I wanted to share. Meaning that the fragment is now available to be used as a destination from other graphs. I think this is the correct solution. This forces you to think about your app flow and how you design your navigation graphs.

Take a look at: Nested Graphs

The main idea is that nested graphs should aim to represent an "independent" or "self-contained" flow of your app. If you need to "share" one of your fragments in one graph with other graphs, then there may be something wrong with your design. In my case it made me realize that the nested graph that contained my shared fragment was not necessary and didn't actually represent an independent flow of the app, it was better embedded in the main flow, which was the other graph that wanted to have access to the shared fragment. The good thing about using graphs is that it forces you to consider all these flows details, which can eventually help you to build better UI/navigation experience for the user.

marcelo-s avatar Jun 30 '20 22:06 marcelo-s

I have even tried to create a nested graph per destination (means that graphs will contain only one single fragment which allows me to avoid the problem mentioned by @marcelo-s) and include them into a different graphs. Unfortunately in that case SafeArgs plugin does not work properly and auto-generated FragmentDirections does not contain actions and arguments.

msahakyan avatar Jul 06 '20 17:07 msahakyan

I have even tried to create a nested graph per destination (means that graphs will contain only one single fragment which allows me to avoid the problem mentioned by @marcelo-s) and include them into a different graphs. Unfortunately in that case SafeArgs plugin does not work properly and auto-generated FragmentDirections does not contain actions and arguments.

Well if you have 1 to 1 relationship between graphs and fragments, then there is no point in having "multiple graphs". In that case you can put all of the Fragments in one graph, that way you will for sure have access to any fragment you want.

I also had the issue of the Fragment Directions not being generated. Make sure you can build your app and build it, meaning you shouldn't have any errors on your project, that way gradle/maven can compile and generate the Classes with the actions.

marcelo-s avatar Jul 06 '20 17:07 marcelo-s

@marcelo-s It's not about 1 to 1 relationship between graphs. The idea was to create a nested subgraph (with single destination-fragment inside) for every fragment which is going to be injected into multiple graphs. Then instead of every time directly registering a corresponding destination as a <fragment id=... we can include it like <include app:graph="@navigation/subgraph" />. The advantage of this approach would be that you will have a single file (entry-point) for each shared fragment(between multiple graphs) and everywhere instead of registering the same fragment again and again (with exactly same actions and arguments) you could just include it as a subgraph. Unfortunately this approach does not work because in case of <include app:graph="@navigation/subgraph" /> when SafeArgs plugin generates FragmentDirections it does not contain actions and arguments.

msahakyan avatar Jul 07 '20 06:07 msahakyan

Unfortunately this approach does not work because in case of when SafeArgs plugin generates FragmentDirections it does not contain actions and arguments.

Workaround: Add an action with the same id to both root graph and subgraph (ex showSome). Add arguments to SubgraphFragment, then navigate from SomeRootFragment via SubgraphFragmentDirections.showSome(args) instead of SomeRootFragmentDirections.showSome().

alashow avatar Aug 17 '20 04:08 alashow