6

I have a Fragment A which navigates to Fragment B

Fragment B hosts a ViewPager2.

ViewPager2 has two fragments inflated in it - Fragment C and Fragment D.

On clicking an item in Fragment C I want to navigate to a new instance of Fragment D on top of Fragment B.

Currently, my code is something like this -

findNavController().navigate(
            R.id.action_FragmentC_to_FragmentD,
            bundleOf("id" to id, "type" to "list")
        )

However, when I try to navigate I get the following exception -

java.lang.IllegalArgumentException: Navigation action/destination com.test.at:id/action_FragmentC_to_FragmentD cannot be found from the current destination Destination(com.krtkush.audiotime:id/FragmentB) label=FragmentB

From what I can understand is that the navigation component is still on Fragment B but I'm trying to navigate to Fragment D from Fragment C and hence it is throwing an exception.

I (think) can fix this by adding a listener which informs Fragment B when the item is tapped in Fragment C and then navigate to Fragment D from Fragment B. However, this will make my Fragment C tightly coupled to Fragment B which I don't want to. Anyway to fix this is another way?

krtkush
  • 1,378
  • 4
  • 23
  • 46

1 Answers1

7

If you do not navigate() to Fragment C and Fragment D, you will remain on the last destination you navigated to: Fragment B, that is the expected behavior. The NavController knows nothing about child fragments such as fragments within a ViewPager of Fragment B and therefore you were never on Fragment C as a destination.

If you never navigate() to Fragment C and it is only viewable as part of your ViewPager, then Fragment C should not be in your graph. Any actions from fragments within Fragment B's ViewPager should be actions on Fragment B directly (the destination you're actually on).

Note that you can reuse the same actions names on fragments such as Fragment D if you are also using them as standalone destinations in your graph (thus ensuring that the action is available in both cases).

ianhanniballake
  • 191,609
  • 30
  • 470
  • 443
  • > "Any actions from fragments within Fragment B's ViewPager should be actions on Fragment B directly (the destination you're actually on)." Does this not tightly couple the fragment to the host activity/ fragment? – krtkush Sep 23 '20 at 19:31
  • You run the exact same `findNavController().navigate()` code, so I don't know what additional coupling you think is happening? – ianhanniballake Sep 23 '20 at 19:33
  • `Fragment C ` will have to inform `Fragment B` that an action has been taken and then `navigate()` will be called. Now, if I want to use `Fragment C` independently somewhere else within the app, it'll have no `Fragment B` to inform but actually call `navigate()` itself. – krtkush Sep 23 '20 at 19:36
  • 1
    No, you don't need to do that at all - `Fragment C` can call `findNavController().navigate()` itself without any problems. Your action just needs to be on `Fragment B` when you are actually on `Fragment B`. As per the last paragraph, you can certainly use the same action name on `Fragment C` as well if you are using it independently of your ViewPager as well, all without changing `Fragment C`'s code. – ianhanniballake Sep 23 '20 at 19:39
  • how to inform fragment B from fragment C or fragment D. I am getting the same exception when I use @ianhanniballake suggestion. – Shubham Mogarkar Jul 22 '22 at 10:15