I have 4 fragments in a drawer, lets call them fragment A, B, C, D. I use navigation architecture to bind my fragments with the drawer.
Fragment A is my entry point and from there I can navigate anywhere on the drawer.
Suppose I take the path A > B > C > B > C
If I press back from C, it goes to B then to C again and then to B and finally to A, but I don't want that.
When I press the back button from C, I want it to just go back to B then A without recreating fragments that are already in the back stack. Can someone please help on how to achieve this ?
When I press the back button from C, I want it to just go back to B
then A without recreating fragments that are already in the back
stack.
When you are navigating to a destination, you can pop the old instance of the destination from the back stack. Just add the pop inclusive to all your action in nav graph.
<!-- Add this in the actions navigating to B -->
app:popUpTo="#id/B"
app:popUpToInclusive="true"
Explanation
What the above pop behavior will do is, when you are navigating from, say C > B, it will pop everything till B (inclusive) from the back stack and add the latest instance of B on the back stack.
A > B > C > B > C will have a back stack:
A
A, B
A, B, C
A, B
A, B, C
Note:
The inherent assumption here is that this is not a valid case in your example.
A > B > C > D > B > C leads to a back tracking of C > B > D > A. Please be aware that in the above solution when you navigate to second B, it will pop out D from you back stack too!
Related
Is there some way I can prevent certain destinations in my navgraph from being added to the backstack?
For example, lets say I have 5 fragment destinations: A, B, C, D and E.
navgraph looks like this: A -> B -> C -> D -> E -> A (its a loop)
Now B, C, D and E are fragments that I dont want the user to be able to navigate back to. If the user navigates back at any point in the navgraph, I want them to go to the previous A fragment.
I'm currently doing this by overriding onBackPressed with complicated logic that keeps popping the back stack until a fragment A is reached.. It works but it feels far from optimal. If I could simply prevent B, C, D and E fragments from being added to the backstack it would be much simpler.
SOLUTION 1:
The app:popUpTo and app:popUpToInclusive are exactly what you may be looking for
Via the documentation,the xml attributes will
Pop up to a given destination before navigating. This pops all non-matching destinations from the back stack until this destination is found
Let me explain this to you with three fragments A , B, C
A (start) -> B -> C
if I want to navigate to C
and pop all including A(startscreen) then the code will be:
<action
android:id="#+id/B_to_C"
app:destination="#id/C"
app:popUpTo="#+id/A"
app:popUpToInclusive="true" />
if I want to navigate to C and pop all excluding A then the code will be:
<action
android:id="#+id/action_B_to_C"
app:destination="#id/C"
app:popUpTo="#+id/A"/>
SOLUTION 2:
Using the popBackStack method of the NavController class which does the same job as the onBackPressed but in an elegant way
If you have three fragments : A, B, C
And you are currently in fragment C and would like to go back to A before navigating anywhere(or not navigating anywhere if you please)
NavController controller = Navigation.findNavController(view);
controller.popBackStack(R.id.fragmentB, true);
OR
NavController controller = Navigation.findNavController(view);
controller.popBackStack(R.id.fragmentA, false);
where true or false will indicate if you actually want the destination to stay(false) or be popped off the stack too (true)
For Activity A, B, C and D I have a flow like A->B->C->D. When I'm going to start D from C I need to clear A and B from back stack.
I have the following scenario:
A(Bottom) -> B -> C -> D(Top) -back-> A
A(Bottom) -> B -> C -back-> B -back-> A
Once I'm on the top (D fragment) I want to pop B and C fragment. On this way when I press back from D I can to A.
I want to avoid the transitions on B and C when I back from D.
A(Bottom) -> B -> C -> D(Top) -back-> C -back-> B -back-> A
It is even posible?
If I understand your situation correctly, then when creating fragment D right before that you can try getFragmentManager().popBackStack() which will look at your fragment stack and simply pop the last fragment. For this to work, you need to ensure that B and C are on the backstack so when creating those fragments you will need to call addToBackStack(null). Now, when creating fragment D you can just popBackStack() twice and that will bring you back to A. I hope I am understanding your situation correctly.
I'm stuck with an Activity backstack question. Let's say I have 5 activities in my backstack: like Activity A, Activity B, Activity C, Activity D and Activity E. At some point I want the user to go to another Activity G, when pressed on the back button on Activity E. Activity G needs to be put after Activity B, so I want Activity C and Activity D removed from the backstack (otherwise the user would go to Activity D).
Current situation A --> B --> C --> D --> E
Preferred situation A --> B --> G
Now I understand I can use FLAG_ACTIVITY_CLEAR_TOP when Activity G would have been in the backstack. But the Activity isn't. Also I don't want to use FLAG_ACTIVITY_NEW_TASK because then Activities A and B would also be gone.
Another approach would be to put
android:noHistory="true"
within the manifest for Activities C and D, but this would make the user go back to Activity B every time the user pressed the back button from within Activity C or D.
Who can point me in the right direction?
You can try below
C ----startActivityForResult----------> D ---startActivityForResult--> E
handle onActivityResult with result accordingly to finish Activities, make sure its chained action calls
When you start activity from C->D you put finish();
Intent intent=new Intent(C.this,D.class);
startActivity(intent);
finish();
same way for D->G this way it is possible.
I've noticed a strange behaviour when not adding a framgent transaction to the back stack. I have 4 fragments: A, B, C and D. The transaction for the C fragment isn't added to the back stack. First I add A, then B, then C. Then I press BACK. A is displayed, which is normal. Then I add D and I press BACK. The result is that the fragment C is displayed. Is there something I am missing, because I would expect C to be out of the back stack and to see fragment A.
The transaction for the C fragment isn't added to the back stack.
ok.
First I add A, then B, then C. Then I press BACK. A is displayed,
If you have added B to the backstack, it should display B and not A.
Then I add D and I press BACK.
If you have not added C, then it should show B and not C. If it is showing C that means that you have added C to the backstack.
Is there something I am missing.
From my understanding of the situation, you have not added B to the backstack and you have added C to the backstack.