In Navigation Component, how can one detect if fragment is brought to front from a pop event?
I go from A to B, now I close B using back key, it returns to A, now in A (in onViewCreated event) I want to detect it's coming from B.
If we're using a single NavController.
findNavController((R.id.nav_host_fragment)
.addOnDestinationChangedListener{ hostController, destination, _ ->
val push = currentBackStackSize < hostController.bacStack.size // else pop
// Then save current backstack size
}
This solution might not be always correct, but currently I can't think of an edge case. Please feel free to correct me.
Here is my solution.
In A, add a navigation argument with default value false (in the nav_graph.xml)
In B, add a navigation back to A. To handle back button pressed, add the following in onCreate()
requireActivity().onBackPressedDispatcher.addCallback {
val action = BDirections.actionBFragmentAFragment(true)
findNavController().navigate(action)
}
Now you can determine how A appears. Also, use popUpTo to handle circular logic properly. Let me know if you see any flaws in this approach.
Related
I am currently migrating a fairly complex app from overide on back pressed -> onBackPressedDispatcher.
However our previous code overode back press behaviour at the activity level, and i would like to overide from the fragment only where i need very specific back press behaviour, so as to enable predictive back. However what i have found is that the system back seems to pop the entire activity as opposed to popping the last fragment.
So my question is...how can we set android to pop fragments as opposed to activity without providing a custom callback to onbackPressedDispatcher?
Thanks!!!
private val onBackPressedCallback: OnBackPressedCallback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
// Setting enabled true does not allow predictive back
// Setting enabled false does not allow system back to pop fragments off backstack
}
You can use the method of Activity getFragmentManager() and call its popBackStack.
i.e,
getFragmentManager().popBackStack();
or
getFragmentManager().popBackStackImmediate();
I'm using Navigation Component to navigate in my app. I'm working with tree structure and I'm navigating users node by node -> Node == NodeFragment. But now I'm struggling with back navigation to particular node.
E.g.: Image navigation stack with look like this A -> B -> C -> D when user wants to navigate from node D directly to node B I want to popup fragment C, D and go directly to B?
E.g.: You can imagine something like navigating trough folder structure where you are navigation the same fragment again and again. And then you want to go back to particular folder which is not parent of the current one.
But I don't know ho to achieve it with Navigation Component. For navigation I'm using self action. Thanks in advance.
<fragment
android:id="#+id/nodeFragment"
android:name="com.example.NodeFragment">
<action
android:id="#+id/action_chatbotBuilderChildrenFragment_self2"
app:destination="#id/nodeFragment" />
</fragment>
So I found some kind of workaround solution which is pretty simple. It seems that calling NavController.navigateUp() multiple times in sort period of time works just fine. I'm not sure if this is the right solution but it solves my issues.
I was also supprise that even my fragment transition wasn't break after call NavController.navigateUp() multiple times.
Code example:
repeat(numberOfPopUps) {
findNavController().navigateUp()
}
Go into your navigation graph, click on the action (the arrow line) on C -> D, on the right panel (make sure in design mode instead of split or code mode) you will see pop up tp option, then choose Fragment B, that's it. So whenever you are in Fragment D and you click the Back key, the app will nagivate back to Fragment B.
I'm trying to implement this scenario. I have a sign in screen with a sign in button. When the user clicks the button and gets authenticated, I send the user to the profile screen. The problem comes when the user hits the back button. Instead of existing the app, it goes back to the sign in screen, which is bad. If I have had activities, I have called finish() in the sign in activity when going forward to profile activity, and when the user pressed back, it quits the app. How to do the same thing using navigation?
You need to clear the navigation stack. You can do it in many ways.
For example, if you know that you only have a single item in your back stack, you can use popBackStack:
navController.popBackStack()
navController.navigate(Destinations.Profile)
Or you can use popUpTo and specify the first destination you wanna pop up, and add inclusive parameter:
navController.navigate(Destinations.Profile) {
popUpTo(Destinations.Login) {
inclusive = true
}
}
For creating viewModel instance every time when composable is started you need do this:
val viewModel= remember { MyViewModel() }
That's it. No need in popBackStack and e.t.c.
But i recommend you to found way to listen changes of data in your viewModel.
That will be more clear. JetPack Compose gives you another way how to write code and make Android application, so use it)
I'm currently using Android Navigation Architecture in my project. It has a feature that can launch any fragment with a shortcut.
Suppose my navigation graph looks like this: A->B->C->D.
When I'm at fragment A , I directly navigate to fragment D with NavController.navigate(R.id.fragment_d). But when I'm press back button, it returns to fragment A. Is there any way to let the destination navigate back to its parent in navigation graph? (I mean, in this case, D back to C, B then back to A).
Thanks in advance.
Generally, you should always avoid creating a synthetic back stack when within your own app (and only do this when launching your app from a deep link outside your app, i.e., via an app shortcut).
However, you can approach this in one of two ways:
If you're okay with resetting the state on A, you can use NavDeepLinkBuilder to construct a set of Intents suitable for restarting your task on the chosen destination:
navController.createDeepLink()
.setDestination(R.id.destination_d)
.createTaskStackBuilder()
.startActivites()
Just call navigate() multiple times.
navController.navigate(R.id.destination_b)
navController.navigate(R.id.destination_c)
navController.navigate(R.id.destination_d)
I think you should be able to use navControler.navigateUp() on the destination if you have correctly introduced the parent fragment for your fragments. Also, consider the difference between the device back button and up back-arrow to go up to the parent
So I have the following situation and I'm not 100% sure how to solve it right it. It basically involves communication between the back button and two fragments.
Here is a Short Diagram
(Fragment1) (Fragment2) (Back button)
List of Recipes -> Recipe Filters -> List of Recipes
Obviously I'm doing addToBackStack etc. but I'm trying to rely on the back button for navigation instead of using the home button as I'm using that for a navigation drawer action right now.
Is there any way to pass information between fragment 1 / fragment 2 on a back button navigation action?
If not, what should be done instead. I'd like to avoid spawning an activity for the filters fragment instead.
You can do override onBackPressed() and put whatever logic you want there.Code sample:
#Override
public void onBackPressed()
{
// code to be executed when user presses back
super.onBackPressed(); // optional depending on your needs
}
Make sure you implement onBackPressed properly and they are no side effects.