Navigation Component after back current destination not changed - android

I've 2 fragments, A & B
with action:
<action
android:id="#+id/action_a_to_b"
app:destination="#id/b"
app:enterAnim="#android:anim/fade_in"
app:exitAnim="#android:anim/fade_out"
app:popEnterAnim="#android:anim/fade_in"
app:popExitAnim="#android:anim/fade_out"
app:popUpTo="#id/a"/>
after I move from a to b and pressing back,
and then try again to open b from a, the app crashes and the problem is that the navigation graph current destination remains fragment b instead of changing to a.
Update:
if fragment B inherit from Fragment class, it doesn't happen
if fragment B inherit from BottomSheetDialogFragment it does happen
any idea why?
Thanks.

The problem was that i used the tag instead of in the navigation graph...

Related

How to close All fragments with activity programmatically using Jetpack navigation

Here is scenario:
On login activity button click open Activity 2
In Activity 2 multiple fragments and navigate through navgraph
I want to go back on login screen while click on Fragment 3 Finish button
Here what I try but no luck:
findNavController().navigate(
R.id.action_fragment3_to_fragment1,
null,
NavOptions.Builder()
.setPopUpTo(R.id.fragment1, true).build())
You need to close Activity 2 using finish() and the fragments will be closed with the activity, to close Activity 2 from Fragment 3 you can use this line of code inside Fragment 3:
requireActivity().finish()
First, add attributes app:popUpTo='your_nav_graph_id' and app:popUpToInclusive="true" to the action tag.
<fragment
android:id="#+id/signInFragment"
android:name="com.glee.incog2.android.fragment.SignInFragment"
android:label="fragment_sign_in"
tools:layout="#layout/fragment_sign_in" >
<action
android:id="#+id/action_signInFragment_to_usersFragment"
app:destination="#id/usersFragment"
app:launchSingleTop="true"
app:popUpTo="#+id/main_nav_graph"
app:popUpToInclusive="true" />
Second, navigate to the destination, using above action as parameter.
findNavController(fragment).navigate(
SignInFragmentDirections.actionSignInFragmentToUserNameFragment())

Android NavigationComponent - Remove fragment after changing activity

I'm facing an issue concerning the use of navigation component.
I have this hierarchy :
Activity A composed of fragment f1 and fragment f2
Activity B
When I'm on f2, I change activity like this :
button.setOnClickListener {
startActivity(Intent(activityA, ActivityB::class.java))
}
What I would like is : When I go to activity B, the fragment f2 (of activity A) should be removed. So, when I will kill the activity B, I will come back to activity A without fragment f2.
To illustrate the flow :
Activity A (f1 > f2) > Activity B (Need to remove f2)
When I will come back : Activity B > Activity A (f1 only)
I'm using navigation component and I have tried to use the popUpTo and popUpToInclusive options in my nav_graph. I managed to remove the fragment but there is always a glitch when I remove it (i.e. we see the removal of fragment before passing the activity B, so we see the f1 fragment a little time). I would like to make the transaction invisible to user.
Is there a way to do it ? Don't hesistate to ask me if you need more precisions.
Thanks for your answers,
When you're using the navigation component, you can have direction, then use the navigation component to move from origin fragment/activity to destination fragment/activity. For example:
val actionLockToLogin = LockFragmentDirections.actionLockToLogin()
NavHost.findNavController(this).navigate(actionLockToLogin)
In this code, I go from LockFragment, to LoginFragment. Just add the fragments or activities in the navigation's XML. Set an Action from origin fragment / activity to destination fragment / activity. and by using the code I show you, try to navigate between them.

how to navigate back to previous fragment using navigation component while sending data?

I have 4 Fragments , A, B,C.Fragment A will be the main Fragment, I will be navigating from fragment A to Fragment B then Fragment B return with a result to fragment A. Then I will navigate To fragment C from fragment A, and fragment c will do some operations and return a result to fragment A. Each time the fragment A will show and keep the result returned from each fragment
The navigation between fragment A to the other fragment is implemented using this code
val bundle = Bundle()
bundle.putBoolean("data", true)
findNavController().navigate(R.id.myAction, toVoicePassphraseRecognitionbundle)
My problem her is that to return to fragment A, i also use findNavController().navigate()but doing so will create a new fragment that will be added to the stack, so my question is how can i navigate back from fragment B to A, or C to A while keeping the view state as it is without creating a new Fragment A.
The problem is, you are setting Fragment A as destination in your action,
what it does is, it creates a new instance of the Fragment.
What you really want is to go back to, not go to.
So what we we do to go back, we pop our back stack.
<fragment
android:id="#+id/fragmentC"
android:name="com.sample.project.FragmentC"
android:label="FragmentC">
<action
android:id="#+id/navigate_C_to_A"
app:popUpTo="#+id/fragmentA"
app:popUpToInclusive="false" />
</fragment>
popUpTo is where you want to land
popUpToInclusive means do you want this fragment to pop from stack too?
And let say your flow is like A->B->C->A
But Fragment A is unknown, or B and C are the part of flow that can be used at many places, so the A will not be A every time.
In that case :
<fragment
android:id="#+id/fragmentC"
android:name="com.sample.project.FragmentC"
android:label="FragmentC">
<action
android:id="#+id/navigate_C_to_before_B"
app:popUpTo="#+id/fragmentB"
app:popUpToInclusive="true" />
</fragment>
popUpToInclusive is the key here

Kill fragment in navigation controller

My flow of fragment is like this
Main -> A -> B -> C ->A
In fragment c, it has a submit button which will return to A.
When I press back button in A, I want it back to Main. But it return to fragment c instead.
In fragment C, I use this
findNavController().navigate(R.id.action_c_to_a)
nav_graph.xml
<fragment
android:id="#+id/fragmentC"
android:name="xxx"
android:label="xxx">
<action
app:launchSingleTop="true"
app:popUpTo="#+id/fragmentA"
app:popUpToInclusive="true"
android:id="#+id/action_c_to_a"
app:destination="#id/fragmentA" />
</fragment>
Why not pop up to fragment A? You could just call findNavController().popBackStack(R.id.fragmentA, false) instead of navigating with an action.
try to look at my complete solution with removing/killing fragment from backstack.
Navigation Component set transition animation programmatically
You can override the back button behavior to do this.
Provide custom back navigation
The idea is to set a app:popUpTo without setting app:destination. Indeed, setting a app:destination will create a fragment and add it to the backstack which is not what you want.
To you can just remove :
app:destination="#id/fragmentA"
If you have this :
app:popUpTo="#+id/fragmentA"
And it will really pop the backstack until fragmentA

AndroidX navigation navigateUp twice

I am using the new AndroidX navigation framework.
I have a few fragments all linked in a navigation chain.
FragmentA --> FragmentB --> FragmentC
FragmentC has a Cancel button that should send me up all the way back to FragmentA.
Should I do the following:
on FragmentC call the method:
Navigation.findNavController(view).navigateUp();
then on FragmentB listen to some callback and using some passed parameter or argument trigger another navigateUp() function from FragmentB
or is there some method that will do the equivalent of navigateUpTwice()
What I ended up doing was
Navigation.findNavController(view).popBackStack(R.id.fragmant_a,false)
In your navigation.xml file under the action that you have created to navigate to starting fragment (FragmentA in your case) add the following
<action
....
app:popUpTo="#id/fragmentA"
app:popUpToInclusive="false"/>
This will pop up all the fragments until FragmentA and will exclude FragmentA since popUpToInclusive is set to false.
Edit:
The full form of your action under FragmentC tag of your navigation.xml file will be something similar to this:
<fragment
android:id="#+id/FragmentC"
android:name="com.yourdomain.FragmentC"
android:label="FragmentC">
<action
android:id="#+id/action_fragmentC_to_fragmentA"
app:destination="#id/fragmentA"
app:popUpTo="#id/fragmentA"
app:popUpToInclusive="false"/>
</fragment>
Try with this, it works for me.
findNavController().navigateUp()
findNavController().navigateUp()
You can set pop To FragmentA in your action from FragmentB --> FragmentC and when then you press back it goes to Fragment A instead of Fragment B
So I found myself in a situation where I had to navigateUp() twice, but with a twist: I could reach the view through several paths. Think of it like this:
Fragment A --> Fragment C --> Fragment D
Fragment B --> Fragment C --> Fragment D
In a normal situation, using the popTo xml attribute or the popBackStack() method would work. However it is unusable here. Fortunately, what you can do is:
val navController = NavHostFragment.findNavController(this)
navController.navigateUp()
navController.navigateUp
As other people have pointed out, this is absolutely not optimised performance-wise. In any situation where you can reach Fragment D through a single path, use popTo instead.

Categories

Resources