I have two fragments; HomeFragment & NextFragment and I go to the next one with a button from the base fragment. Then via back press I want to go back to the first one, however I end up at the apps home screen. A solution
requireActivity().onBackPressedDispatcher
.addCallback(viewLifecycleOwner, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
findNavController().popBackStack()
}
})
was given here but it did not work. I am using ViewPager2 and saw that the home fragment is destroyed when I go to the next one. How can I solve the problem?
I am working on android application that contains five fragment on an activity, What I want is as the fragment 1 is opened and I back-press it comes to Main fragment and same as I press back-press from fragment 5 it also comes to Main fragment.
and When I press on Backpress from MainFragment, the App should Exit.
I have Gone through this link Link
and I have also added the Dispatcher but It not met my requirement.
Like I am always opening each fragment like this
private fun ShowQRCodeFragment() {
val newFragment: Fragment = QrCodeScanningFragment()
val transaction1: FragmentTransaction = supportFragmentManager.beginTransaction()
transaction1.replace(R.id.frameLayout, newFragment)
transaction1.addToBackStack(null)
transaction1.commit()
}
Updated the transaction
private fun FunctionNewSettings() {
val newFragment: Fragment = CustomSettingsFragment()
val transaction1: FragmentTransaction = supportFragmentManager.beginTransaction()
transaction1.replace(R.id.frameLayout, newFragment)
transaction1.addToBackStack("namedata")
fragmentManager.popBackStack()
transaction1.commit()
}
You should use addToBackStack() while fragment transaction. This will allow you to go to the previous fragment on back-press.
For the app exit case, check if the current fragment is MainFragment with the help of fragment tag and calling fragmentmanager.popBackStack() or super.onBackPressed() accordingly.
In MainFragment, use
override fun onAttach(context: Context) {
super.onAttach(context)
val callback = object : OnBackPressedCallback(
true // default to enabled
) {
override fun handleOnBackPressed() {
requireActivity().finish()
}
}
requireActivity().onBackPressedDispatcher.addCallback(
this, // LifecycleOwner
callback
)
}
In another fragments, use
override fun onAttach(context: Context) {
super.onAttach(context)
val callback = object : OnBackPressedCallback(
true // default to enabled
) {
override fun handleOnBackPressed() {
for (i in 0 until (requireActivity() as FragmentActivity).supportFragmentManager.backStackEntryCount) {
activity.supportFragmentManager.popBackStack()
}
}
}
requireActivity().onBackPressedDispatcher.addCallback(
this, // LifecycleOwner
callback
)
}
if u want to go back to the previous fragment first use
addToBackStack()
and if you want to exit the app/activity by using onBackPressed from activity then in MainFragment use
getActivity().onBackPressed();
if you want to finish the activity from Fragment use
getActivity().finish();
You can also replace existing fragment when user clicks Back button using
fragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)
Solution
Override onBackPressed() method inside your activity.
override fun onBackPressed() {
val count = supportFragmentManager.backStackEntryCount
if (count > 1) {
repeat(count - 1) { supportFragmentManager.popBackStack() }
} else {
finish()
}
}
You don't need to mess around with the back button behaviour if you're just switching fragments around, and you shouldn't need to pop the backstack either.
The backstack is just a history, like the back button on your browser. You start with some initial state, like an empty container layout. There's no history before this (nothing on the backstack), so if you hit back now, it will back out of the Activity completely.
If you start a fragment transaction where you add a new fragment to that container, you can use addToBackStack to create a new "step" in the history. So it becomes
empty container -> added fragment
and if you hit back it takes a step back (pops the most recent state off the stack)
empty container
if you don't use addToBackStack, the change replaces the current state on the top of the stack
(with addToBackStack)
empty container -> fragmentA -> fragmentB
(without it)
empty container -> fragmentB
so usually you'll skip adding to the backstack when you add your first fragment, since you don't want an earlier step with the empty container - you want to replace that state
empty container
(add mainFragment without adding the transaction to the backstack)
mainFragment
and now when you're at that first state showing mainFragment, the back button will back out of the activity
So addToBackStack makes changes that are added to the history, and you can step back through each change. Skipping it basically alters the last change instead of making a new one. You can think of it like adding to the backstack is going down a level, so when you hit back you go back up to the previous level. Skipping the add keeps you on the same level, and just changes what you're looking at - hitting back still takes you up a level.
So you can use this to organise the "path" the back button takes, by adding new steps to the stack or changing the current one. If you can write out the stack you want, where the back button takes you back a step each time, you can create it!
One last thing - addToBackStack takes a String? argument, which is usually null, but you can pass in a label for the step you're adding. This allows you to pop the backstack all the way back to a certain point in the history, which is like when a browser lets you jump to the previous site in the history, and not just the last page.
So you can add a name for the transaction, like "show subfragment" when you're adding your first subfragment on top of mainFragment, meaning you can use popBackstack with that label to jump straight to the initial mainFragment state, where the next back press exits the activity. This is way more convenient than popping each step off the backstack, and keeping track of how many you need to do - you can just jump back in the history to a defined point
I have an activity with 4 fragments. on fragment 3 there is a button when i click on that button i go to some other activity(Like TestActivity). I use this code to go from fragment 3 to that TestActivity:
startActivity(new Intent(getActivity(), TestActivity.class));
When i press back button on TestActivity it redirect me to the 1st Fragment(Default) of Main Activity. I want that when user press back on TestActivity to again come to Fragment 3. Please suggest me how i achieve this behaviour. Thanks
First of all you should know it has difference between fragment and activity back stack.
In change your fragment you should use add addToBackStack("name") , something like this :
KOTLIN :
In fragment :
requireActivity().supportFragmentManager.beginTransaction()
.replace(R.id.framelayout_main_fragmentContainer,SecondFragment())
.addToBackStack("first")
.commit()
In activity :
supportFragmentManager.beginTransaction()
.replace(R.id.framelayout_main_fragmentContainer,Firstfragment())
.addToBackStack("first")
.commit()
JAVA :
getFragmentManager().beginTransaction().
replace(R.id.framelayout_main_fragmentContainer, Firstfragment()).
addToBackStack("first").commit();
Suppose we have three fragments hosted in an activity on our back stack
A->B->C
When I click on back press on fragment C I also want to immediately remove B from the back stack.Note that in some cases I might want to go back to B but for the most part I want to clear out C and B together to get to A.How can I achieve this should I call popBackStack() twice or should I have some kind of delegate mechanism to notify B that C has been closed and we don't expect to show B so please clean up.
In fragment A do this..
getSupportFragmentManager().beginTransaction()
.add(R.id.containerMain, new FragmentA()).addToBackStack("BACKSTACK_FRAGMENT_A")
.commit();
and do not use addToBackStack(..)
in this case you'll always return to Fragment A when you press back from other Fragments.
and when are going to specify back press to specific fragment
Add Fragments To BackStack. Before commit() the transaction, use addToBackStack() method i.e
addToBackStack("Some String").commit();
and in onBackPressed()
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
this.finish();
}
}
My app use 5 fragment, like this:
[1]through[onClick on actionBar defined in activity]->[2]->[3]->[4]->[5]
Each fragment is added to the back stack so I can go back while pressing the back button. However, I would like to return to the first fragment when pressing the back button on the 5th fragment, like this:
[1]<-[2]<-[3]<-[4] [1]<-[5]
I tried to make it this way:
fragmentTransaction.addToBackStack("firstfragmenttag");
When adding the 5th fragment on the 4th one, but when I press the back button it still send me back to the 4th instead of the 1st! Is it a simple way do do that programmatically? Thanks in advance.
In your case, you just need to add first fragment in stack.
No need to add others to stack
This could be achieved in following way:
Fragment F1 = new <Fragment Name>();
fragmenttransaction.add(R.id.content,F1).commit();
And for others like F2,F3,F4 & F5
you could use
Fragment F2 = new <Fragment Name>();
fragmenttransaction.replace(R.id.content,F2).addToBackstack(null).commit();
And then you need to override OnBackpressed [inside Activity] like below:
#Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount() >0) {
getSupportFragmentManager().popBackStack();
}
else{
super.onBackPressed();
}
}
Hope it helps!
you can actually get the backstack count in onBackPressed and check count , if it is 5 then perform popfrombackstack 4 times to get back to 1 fragment