导航组件:从ViewPager中的Fragment导航到另一个Fragment

6

我有一个名为Fragment A的碎片,它可以导航到Fragment B

Fragment B托管了一个ViewPager2

ViewPager2中有两个碎片——Fragment CFragment D

Fragment C中单击某个项后,我想在Fragment B上方导航到Fragment D的新实例。

目前,我的代码类似于以下内容 -

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

然而,当我尝试导航时,会出现以下异常 -

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

根据我理解,导航组件仍然停留在“片段B”,但我正在尝试从“片段C”导航到“片段D”,因此它抛出了异常。
我认为可以通过添加监听器来解决这个问题,在“片段C”中向“片段B”发送信息,以便在“片段B”中导航到“片段D”。然而,这会使我的“片段C”与“片段B”紧密耦合,而我不想这样。是否有其他方法可以解决这个问题?
1个回答

7
如果您不使用navigate()方法导航到Fragment CFragment D,您将保留在最后一个目的地上:即Fragment B,这是预期的行为。NavController并不知道子片段,例如在Fragment BViewPager中的片段,因此您从未在Fragment C作为目标上。
如果您从未使用navigate()方法导航到Fragment C,并且它仅可作为ViewPager的一部分查看,则Fragment C不应该在您的图形中。 Fragment B ViewPager中的片段的任何操作都应直接在Fragment B上执行(您实际上正在其上的目标)。
请注意,如果您还将它们用作独立目标,则可以在诸如Fragment D之类的片段中重用相同的操作名称(从而确保在两种情况下均可用)。

“Fragment B的ViewPager中的任何操作都应直接作用于Fragment B本身(您实际上所在的目标位置)。这难道不会将Fragment与宿主Activity / Fragment紧密耦合吗?” - krtkush
你运行完全相同的 findNavController().navigate() 代码,所以我不知道你认为发生了什么额外的耦合? - ianhanniballake
“Fragment C”将不得不通知“Fragment B”已经采取了某个操作,然后将调用“navigate()”。现在,如果我想在应用程序的其他地方独立使用“Fragment C”,它将没有“Fragment B”来通知,但实际上会自己调用“navigate()”。 - krtkush
1
不,你完全不需要这样做 - Fragment C 可以自己调用 findNavController().navigate() 而没有任何问题。只要当你实际上在 Fragment B 上时,你的操作就需要在 Fragment B 上。根据最后一段,如果你也在独立于你的ViewPager使用它的情况下,你肯定可以在 Fragment C 上使用相同的操作名称,而不改变 Fragment C 的代码。 - ianhanniballake
如何从片段C或片段D通知片段B。当我使用@ianhanniballake的建议时,我得到了相同的异常。 - Shubham Mogarkar
@ianhanniballake 不行,如果从其他的 Fragment E 单独打开 Fragment C,我们不能重复使用相同的代码。在这种情况下,Fragment C 有一个在按钮点击时触发的代码 findNavController().navigate(FragmentBDirections.actiontoFragmentC())。它会抛出异常,指示在目标 Fragment E 上找不到该操作。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接