I have Fragments X, A, B, and i'm using Navigation architecture component to navigate between them.
Fragments A, B specific, but Fragment X can be any(C,D,...);
Fragments A and B from Bottom Navigation and their "navigations icons" always on the screen, it means user can go to A or B anytime from any Fragment(include A and B):
X -> A -> B
X -> B -> A
A -> B -> X
A -> B -> A
//another ways
My problem about this case:
X -> A -> B -> A -> B -> ?
If user started from X
, reached ?
and begin to go back by "back" button, he goes throw A
,B
several times:
User pressed back:
? -> B -> A -> B -> A -> X
But I want "to exclude" fragments from backstack if they already on it:
? -> A -> B -> X
If user navigate:
X -> A -> B -> A
I want to see:
A -> B -> X
Not:
A -> B -> A -> X
I'm trying to do it with Pop To, but it can return me on one one concrete Fragment only. I need to return on my started X Fragment, not hardcoded. Inclusive and Single top is not about it.
I'm not sure i can do it with basic Navigation component, so i need your advice. If i can't do it, what way should i use? Is there any good practices about it?
UPD:
I'm using global points to navigate between Fragments. It's how my navigation looks like:
The right|bottom chain is X, i can navigate from any of it to to not chanied fragments using bottom navigation. It's Single Activity app, to navigate i'm using just:
//Using global points
findNavController(R.id.host).navigate(R.id.toLibrary)
the following Solution employs Fragment Visibility Technique in order to Manage Fragments Backstack
when onBackPressed()
.
We Assign a Tag to each Fragment
when it's Called & Invoked to make it possible to Recognize which of Fragment
s have been Added to Backstack
and are predecessors.
by below code, we assign a tag to a Fragment
that is going to be Transacted.
fragmentManager.beginTransaction()
.replace(R.id.FragmentHolder, Fragment_A OR Fragment_B OR Fragment_ANY, "A or B or ANY")
.addToBackStack(tag).commit();
Remember you must assign a tag to any Fragment that you want to be Transacted.
We are going to Handling public void onBackPressed()
.
You MUST ignore super.onBackPressed()
Because, we don't Want to defualt onBackPressed
Method to Impact Backstack(as it is) while back button is pressed. Moreover, we Want to Handle Backstack ourselves.
Here you go
@Override
public void onBackPressed() {
if(isVisible("A")) { //Go some where else you wanna go }
else if(isVisible("B")){ //Go some where else you wanna go }
else if(isVisible("X or any"){ //Go some where else you wanna go }
else { //Go default page }
}
public boolean isVisible(String tag){
try {
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment != null && fragment.isVisible())
return true;
else
return false;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
When back button is pressed, We check which Fragment
is already Visible and do Redirect the user to the Corresponding Predecessor Fragment
.
For Ex: A - > B
OR A -> X
OR X -> B
I am using this Technique for a Released Application and all good.