0

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()
}
Usman Ali
  • 425
  • 1
  • 9
  • 31
  • First of all null should not be there in addToBackStack. Second if you want to maintain backstack, register onBackPressedDispatcher in your fragment else you can manage it in parent activity but counting backstack entry. – Bhavnik Dec 07 '20 at 06:43
  • How Can I done this in Main Activity by Counter – Usman Ali Dec 07 '20 at 06:44
  • and how would I attach a dispatcher – Usman Ali Dec 07 '20 at 06:45
  • You can get the backstackentrycount using getSupportFragmentmanager, google it. You will get your solution. – Bhavnik Dec 07 '20 at 06:46

5 Answers5

2

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.

tronku
  • 490
  • 4
  • 12
2

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
        )
    }
Dharman
  • 30,962
  • 25
  • 85
  • 135
GianhTran
  • 3,443
  • 2
  • 22
  • 42
1

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)

  • I have added this but when the fragment 2 is opened on main activity layout It also backpress that Activity.... What I want is as I click on Fragment 2 it should back to main fragment on main activity and when i press back on mainfragment it exit the app – Usman Ali Dec 07 '20 at 06:53
  • then u can try replacing the existing fragment with a new one – trinadh thatakula Dec 07 '20 at 07:01
  • But Replacing Might take Time – Usman Ali Dec 07 '20 at 07:02
  • I have added fragmentmanager.popBackStack() after transaction1.addToBackStack(null) it goes to previous fragment which one it is rather fragment 2 or 5, But I want is It always goes to Initial fragment – Usman Ali Dec 07 '20 at 07:03
  • try passing some name to back stack in place of null – trinadh thatakula Dec 07 '20 at 07:12
1

Solution

Override onBackPressed() method inside your activity.

override fun onBackPressed() {
    val count = supportFragmentManager.backStackEntryCount
    if (count > 1) {
        repeat(count - 1) { supportFragmentManager.popBackStack() }
    } else {
        finish()
    }
}
Son Truong
  • 13,661
  • 5
  • 32
  • 58
1

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

cactustictacs
  • 17,935
  • 2
  • 14
  • 25