Android navigation component exclude fragment from back stack - android

I need to exclude Fragment from back stack.
I know there are many questions here regarding this issue, but I cousin't find an answer to my issue.
Let's say I have Fragment A and Fragment B. Fragment A is move to Fragment B and Fragment B open another Activity. What I need is when I click back from that Activity go back to Fragment A.
Below is my XML of the graph:
<fragment
android:id="#+id/nav_liabilities_fragment"
android:name="liabilities.liabilities_list_fragment.view.LiabilitiesListFragment"
android:label="LiabilitiesListFragment"
tools:layout="#layout/fragment_liabilities_list">
<action
android:id="#+id/action_nav_liabilities_fragment_to_nav_missing_liability_details_fragment"
app:destination="#id/nav_missing_liability_details_fragment"
app:popUpTo="#+id/nav_liabilities_fragment"
app:popUpToInclusive="false"
/>
</fragment>
<fragment
android:id="#+id/nav_missing_liability_details_fragment"
android:name="ui.flow.lobby.liabilities.missing_liability_details.view.MissingDetailsLiabilityFragment"
android:label="MissingDetailsLiabilityFragment"
tools:layout="#layout/fragment_missing_details_liability">
<argument
android:name="extra_data"
app:argType="android.repository.network.model.response.liabilities.LiabilityModel" />
</fragment>
</navigation>

Related

How to navigate to fragment with arguments without recreating it?

I have a question. I'm using nav component for navigation. For example i have fragment A, B and C and bottomNavigation. I'm using
binding.bottomNavigation.setupWithNavController(navController)
For multiple backstack. But here is situation: Main frag is A. I'm moving to fragment B or C. I have buttons on fragments B and C which should lead me to fragment A with putted arguments in it so i'm using just:
findNavController().navigate(fragmentBDirections.fromFragmentBToFragmentA(argument))
But here is a problem. I'm recreating fragment A after this but i'm already have this fragment in backstack. So is it possible to find A in backstack and navigate to it without recreating? Is it possible to save backstack after that?
Your problem seems like an ideal case to use a sharedViewModel
Your button in B or C should pop and fallback to A after updating a property in the viewModel. On leaving, the viewModel is not destroyed because it is bound to the activity and is available for Fragment A.
Bonus is using LiveData so that the change is observed and updated automatically
I think SavedStateHandle might be helpful.
<Navigation>
<fragment
android:id="#+id/BFragment"
android:name="com.packageName.app.BFragment"
android:label="fragment_b"
tools:layout="#layout/fragment_b" >
<action
android:id="#+id/action_BFragment_pop_including_AFragment"
app:popUpTo="#id/AFragment"
app:launchSingleTop="true" />
</Navigation>
<Navigation>
<fragment
android:id="#+id/CFragment"
android:name="com.packageName.app.CFragment"
android:label="fragment_c"
tools:layout="#layout/fragment_c" >
<action
android:id="#+id/action_CFragment_pop_including_AFragment"
app:popUpTo="#id/AFragment"
app:launchSingleTop="true" />
</Navigation>
try it . it's my solution

backstack does not clear while navigating from fragment to activity

Here is my code
<fragment
android:id="#+id/fragment1"
android:name="com.example.app.Fragment1"
android:label="SignatureFragment"
tools:layout="#layout/layout_fragment1">
<action
android:id="#+id/action_fragment1_to_main_activity"
app:destination="#id/main_activity"
app:enterAnim="#anim/slide_in_from_right"
app:exitAnim="#anim/no_anim"
app:launchSingleTop="true"
app:popEnterAnim="#anim/no_anim"
app:popExitAnim="#anim/slide_out_to_right"
app:popUpTo="#id/navigation_graph_id"
app:popUpToInclusive="true" />
</fragment>
<activity
android:id="#+id/main_activity"
android:name="com.example.app.MainActivity"
android:label="MainActivity"
tools:layout="#layout/activity_main" />
Now the code for navigation
findNavController().navigate(R.id.action_fragment1_to_main_activity)
When I navigate to activity and press back, the fragment is still there. I want to clear the backstack after opening the activity.
I tried to remove the animation and also tried with removing app:launchSingleTop, but no success.
Edit
Jetpack Navigation is intended to work with single activity and does not fully support activity navigation with parameters passed to actions
Thus to clear stack when navigating from one activity to another you will still need to call activity.finish()
Edit end
The thing is findNavController().navigate(R.id.action_fragment1_to_main_activity) wont work.
Try to navigate via navigate(#NonNull NavDirections directions). In your case it will look something like this
findNavController().navigate(
Fragment1Directions.actionFragment1ToMainActivity())
Hope it helps.

How can I go back directly to Fragment A since Fragment D without going back to Fragment C?

I use Android Navigation Architecture Component.
I have three Fragment A, B and C
Fragment A -> Fragment B -> Fragment D
Fragment A -> Fragment C -> Fragment D
On fragment D I have a button used to validate modifications and finish.
From this Frgament D I would like to:
return to Fragment B when I come from Fragment B (I use findNavController().navigateUp())
come back to Fragment A when I come from Fragment C (I don't know how to do it)
How can I go back directly to Fragment A when I come from Fragment D without going back to Fragment C?
Should I wait for the return on Fragment C and reprocess for the execution of findNavController().NavigateUp().
I use setPopUpTo on NavOptions, or you can use it inside the xml as well
documentation => https://developer.android.com/reference/androidx/navigation/NavOptions.Builder#setPopUpTo(int,%20boolean)
You can achieve both of these action with findNavController().NavigateUp()
Given the following graph for example:
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/test_nav_graph"
app:startDestination="#id/a">
<fragment
android:id="#+id/a"
android:name="fragment.A"
tools:layout="#layout/a_fragment"
android:label="A" >
<action
android:id="#+id/action_a_to_b"
app:destination="#id/b" />
<action
android:id="#+id/action_a_to_c"
app:destination="#id/c" />
</fragment>
<fragment
android:id="#+id/b"
android:name="fragment.B"
tools:layout="#layout/b_fragment"
android:label="B" >
<action
android:id="#+id/action_b_to_d"
app:destination="#id/d" />
</fragment>
<fragment
android:id="#+id/c"
tools:layout="#layout/c_fragment"
android:name="fragment.C"
android:label="C" >
<action
android:id="#+id/action_c_to_d"
app:destination="#id/d"
app:popUpTo="#id/a"/>
</fragment>
<fragment
android:id="#+id/d"
tools:layout="#layout/d_fragment"
android:name="fragment.D"
android:label="D" />
</navigation>
When you take the path: A->B->D your back stack is A,B,D and when you call NavigateUp() you go back to B.
Now the path A->C->D has a minor addition in the action tag as you can see
<action
android:id="#+id/action_c_to_d"
app:destination="#id/d"
app:popUpTo="#id/a"/>
it has popUpTo, so when you navigate from C to D app:popUpTo tells the Navigation library to pop some destinations off of the back stack as part of the call to navigate(), so after navigating to D your back stack is A,D and NavigateUp() takes you back to A
So when you are in Fragment D and pressing back button . You can check the fragment stack and check for example
onBackPress(){
childFragmentManager.popbackstack()
val currentFragment = findFragmentByTag("FRAGMENT_B")
if(currentFragment == childFragmentManager.primaryNavigation()){
childFragmentManager.popbackstack()
}
NOTE
Above snippet is written without editor. You can use this logic.

Is it possible to start with a "non-start" fragment using Android Navigation Architecture Component(Android Jetpack)?

so I have the following navigation graph:
Fragment A (start) --> Fragment B
So for some situations (firebase notifications), I need to start Fragment B directly, passing data from the notifications. Now, this works. However, when I press the back button, it results in a crash. Is it because the leading fragment (Fragment A) is not in the stack? If so, is there a way to properly handle this.
Basically, I need the backPressed action to launch the start Fragment (Fragment A) in a situation where Fragment B is launched directly without passing through Fragment A.
Below is a snippet of my graph:
<fragment
android:id="#+id/homeFragment"
android:name="dita.dev.myportal.ui.home.HomeFragment"
android:label="Home"
tools:layout="#layout/fragment_home">
<action
android:id="#+id/action_homeFragment_to_messageDetailFragment"
app:destination="#id/messageDetailFragment"
app:exitAnim="#anim/fade_out_animation" />
</fragment>
<fragment
android:id="#+id/messageDetailFragment"
android:name="dita.dev.myportal.ui.messages.details.MessageDetailFragment"
android:label="Message"
tools:layout="#layout/fragment_message_detail">
<argument
android:name="title"
app:argType="string" />
<argument
android:name="message"
app:argType="string" />
</fragment>
I hope the link helps.
https://developer.android.com/guide/navigation/navigation-deep-link
Deep links allow for synthetic back-stacks.
Quoted from the website, "This means that when a user presses the Back button from a deep link destination, they navigate back up the navigation stack just as though they entered your app from its entry point."
Maybe trying to create a deep link for Fragment B will work.

Android NavigationUI - Handle backpress when starting fragment is poped out

I am using NavigationUI of android architecture components with bottom navigation in my android app. I have the following situation
The app starts at Fragment A
Initial calculation is done and now I pop out Fragment A by navController.popBackStack()
The app goes to Fragment B (This serves as a 'Home' for the app)
Now there are more fragments say C and D
The user can navigate between B, C and D
Now the problem is in my navigation graph, my starting fragment was A (by defining app:startDestination="#id/fragmentA") but that is now pop out of the activity. Due to this, anytime if I backpress, the app just closes instead going back to the previous fragment. For example, let's say I navigate to Fragment C or D from fragment B and if I press back button, my app will close instead of going to fragment B. If the there way to 'reassign' the startDestination?
I checked the answer to this question which has a similar situation as above but using NavOptions is somehow not working. Is there any other way? Following is the code I used to pop fragment and add nav options
navController.popBackStack()
val navOptions: NavOptions = NavOptions.Builder()
.setPopUpTo(R.id.homeFragment, true)
.build()
navController.navigate(R.id.action_fragmentA_to_fragmentB, null, navOptions)
Use this navigation graph. Hope it will solve your problem.
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/nav_graph"
app:startDestination="#id/fragment_a">
<fragment
android:id="#+id/fragment_a"
tools:layout="#layout/fragment_a">
<action
android:id="#+id/action_a_to_b"
app:destination="#id/fragment_b"
app:popUpTo="#id/fragment_a"
app:popUpToInclusive="true"/>
</fragment>
<fragment
android:id="#+id/fragment_b"
tools:layout="#layout/fragment_b">
<action
android:id="#+id/action_b_to_c"
app:destination="#id/fragment_c"/>
</fragment>
<fragment
android:id="#+id/fragment_c"
tools:layout="#layout/fragment_c">
</fragment>
</navigation>
Use the following line for navigation:
navController.navigate(R.id.action_a_to_b)
navController.navigate(R.id.action_b_to_c)

Categories

Resources