I am trying to build the following view structure/ navigation using ViewPager2 + FragmentStateAdapter + navigation component.
Preconditions: Single activity architecture, with one navigation graph
1. Fragment A holds a view pager. View pager uses FragmentStateAdapter.
2. Fragment B is instantiated via FragmentStateAdapter ("lives" in view pager).
3. Fragment C - should be navigated to from Fragment B. --> This is where the problem is.
Approach 1 : ViewPager2 + FragmentStateAdapter + navigation declared from Fragment B
<fragment
android:id="@+id/fragmentA"
android:name="com.abc.FragmentA"
android:label="FragmentA" />
<fragment
android:id="@+id/fragmentB"
android:name="com.abc.FragmentB"
android:label="FragmentB">
<action
android:id="@+id/to_fragmentC"
app:destination="@id/fragmentC" />
</fragment>
<fragment
android:id="@+id/fragmentC"
android:name="com.abc.FragmentC"
android:label="FragmentC" />
FragmentB executes:
FragmentBDirections
.toFragmentC()
.let { findNavController().navigate(it) }
Result :
App crash
java.lang.IllegalArgumentException: navigation destination com.abc:id/to_fragmentC is unknown to this NavController
Approach 2 : ViewPager2 + FragmentStateAdapter + navigation declared from Fragment A
<fragment
android:id="@+id/fragmentA"
android:name="com.abc.FragmentA"
android:label="FragmentA" >
<action
android:id="@+id/to_fragmentC"
app:destination="@id/fragmentC" />
</fragment>
<fragment
android:id="@+id/fragmentB"
android:name="com.abc.FragmentB"
android:label="FragmentB">
</fragment>
<fragment
android:id="@+id/fragmentC"
android:name="com.abc.FragmentC"
android:label="FragmentC" />
FragmentB executes:
FragmentADirections
.toFragmentC()
.let { findNavController().navigate(it) }
Result:
App navigates to FragmentC, but when i hit the back button , it crashes with :
java.lang.IllegalArgumentException
at androidx.core.util.Preconditions.checkArgument(Preconditions.java:36)
at androidx.viewpager2.adapter.FragmentStateAdapter.onAttachedToRecyclerView(FragmentStateAdapter.java:132)
at androidx.recyclerview.widget.RecyclerView.setAdapterInternal(RecyclerView.java:1209)
at androidx.recyclerview.widget.RecyclerView.setAdapter(RecyclerView.java:1161)
at androidx.viewpager2.widget.ViewPager2.setAdapter(ViewPager2.java:461)
at com.abc.FragmentA.viewCreated(FragmentA.kt:69)
Approach 3 : ViewPager + FragmentStatePagerAdapter (deprecated) + navigation declared from Fragment B
The same result as approach 1.
Approach 4 : ViewPager + FragmentStatePagerAdapter (deprecated) + navigation declared from Fragment A
This one actually works. Also, the navigation back works fine.
The problem here is that:
- Navigation has to be defined for every parent fragment of FragmentB -> not so scaleable
- Usage of the adapter that is deprecated
If anybody knows some elegant solution to this problem, I would be very glad for any hints.
Thank you