Reputation: 151
First of all, I'm sorry if this is duplicate of any threads, I have searched and I found nothing really similar to my case, or at least nothing that could help me solve my problem.
Basically I would like to know what is the best way to navigate between fragments when calling the onBackPressed() method in a simple and clean way.
I have an Activity that calls a fragment (let's call it ListFrag). This ListFrag shows a list of items that when clicked, will call another fragment with details of this item (let's call it DetailFrag). This is simple and everything works well: ListFrag calls DetailFrag, pressing the Back Button will simply navigate backwards as expected. Good!
But my problem is that now I included an extra step between ListFrag and DetailFrag. Now, ListFrag will call another Fragment called PagerFrag, that will allow us to make pagination by Swiping (using FragmentStatePagerAdapter), showing the multiple DetailFrags one after the other. And plus, I need to support two cases:
Case 1: User uses a smartphone and the navigation flow would be ListFrag > PagerFrag > DetailFrag, whatever the device's orientation.
Case 2: User is using a tablet, which will work as the first Case if it's in Portrait orientation mode, but if it is in Landscape mode, it will have to ignore the PagerFrag (we won't be able to make pagination by swiping) and display both ListFrag and DetailFrag on the same layout.
Again I did some work and it works pretty well in all the cases. The main problem is when navigation BACKWARDS: pressing the BackButton became a nightmare, because I'm completely confused about how the FragmentManager is stacking the Fragments (or FragmentTransactions, if I'm not wrong), since the PagerFrag adds more than one DetailFrag to the stack (the previous, the current and the next in the Pager). I have to constantly check "if(fragment is DetailFrag)" in the onBackPressed() method to be able to tell the app where to go next.
And think of this situation: The user is using a Tablet in Portrait mode. The user navigates ListFrag > PagerFrag > DetailFrag. Then, the user change the device orientation. I have to "kill" the Pager and the DetailFrag, recreate the ListFrag with the other xml layout (the one that shows 2 fragments side-by-side) and inflate a DetailFrag there.
It's working, but all those workarounds are ugly and are really, reeeeally not following Best Practices. It makes the code very boring to maintain/reuse.
I'm using one single ViewModel to connect the Activity and the 3 Fragments, and with LiveData I manage to display the info in the UI properly. The data of the items are not the problem, just the backward navigation between all those fragments.
I tried to handle each specific situation when the Activity is recreated or when the user navigates back, but I don't like this approach.
My current solution is something like this:
override fun onBackPressed() {
if (supportFragmentManager.backStackEntryCount == 0) {
super.onBackPressed()
} else {
if(supportFragmentManager.fragments.first() is PagerFrag ||
(!viewModel.isTwoPane)){
/* isTwoPane indicates if we will have 2 fragments side by side if it's a tablet in landscape mode */
for(frag in supportFragmentManager.fragments) {
if(frag is DetailFrag) {
supportFragmentManager
.beginTransaction()
.remove(frag)
.commit()
}
}
}
supportFragmentManager.popBackStackImmediate()
}
}
And a few more lines in the onCreatedView() method of the Fragment, to handle in case the Activity gets recreated (orientation change).
So I expect to find a simple way to navigate backwards between the Fragments without having to check things like "Is the user using a tablet in landscape mode and is he viewing the DetailFrag? So do this, this and that." I would prefer to avoid using the new AndroidX Navigation for the moment, as I'm dealing with a (somewhat) complex project.
Thank you for your time, let me know if I need to provide more info/context!
Upvotes: 1
Views: 48
Reputation: 151
After struggling a little bit more against the Back Stack and all the instance-checking in the onBackPressed() method, I decided to give another try to AndroidX Navigation Architecture like JDevoloper suggested in the comments, and turns out it worked perfectly. It is indeed a great solution. I still had some issues with the ViewPager and with handling the navigation while changing the device orientation, but now everything is solved and working as expected. Thank you for the help!
Upvotes: 1