Show confirmation on back/up in Fragment with Navigation Architecture Component

android navigation component backstack
finish fragment on back pressed
back button navigation in fragment android
android navigation component back button
android onbackpressed
how to add back button in fragment in android
android fragment onbackpressed
android fragment back button example

I am using the Navigation Architecture Component for Android.

For one of my fragments I wish to intercept "back" and "up" navigation, so that I can show a confirmation dialog before discarding any unsaved changes by the user. (Same behavior as the default Calendar app when you press back/up after editing event details)

My current approach (untested) is as follows:

For "up" navigation, I override onOptionsItemSelected on the fragment:

override fun onOptionsItemSelected(item: MenuItem?): Boolean {
    if(item?.itemId == android.R.id.home) {
        if(unsavedChangesExist()) {
            // TODO: show confirmation dialog
            return true
        }
    }
    return super.onOptionsItemSelected(item)
}

For "back" navigation, I created a custom interface and callback system between the fragment and its activity:

interface BackHandler {
    fun onBackPressed(): Boolean
}

class MainActivity : AppCompatActivity() {
    ...

    val backHandlers: MutableSet<BackHandler> = mutableSetOf()

    override fun onBackPressed() {
        for(handler in backHandlers) {
            if(handler.onBackPressed()) {
                return
            }
        }
        super.onBackPressed()
    }

    ...
}

class MyFragment: Fragment(), BackHandler {
    ...

    override fun onAttach(context: Context) {
        super.onAttach(context)
        if (context is MainActivity) {
            context.backHandlers.add(this)
        }
    }

    override fun onDetach() {
        (activity as? MainActivity)?.backHandlers?.remove(this)
        super.onDetach()
    }

    override fun onBackPressed(): Boolean {
        if(unsavedChangedExist()) {
            // TODO: show confirmation dialog
            return true
        }
    }

    ...
}

This is all pretty gross and boilerplatey for such a simple thing. Is there a better way?


As of androidx.appcompat:appcompat:1.1.0-beta01, in order to intercept the back button with navigation component you need to add a callback to the OnBackPressedDispatcher. This callback has to extend OnBackPressedCallback and override handleOnBackPressed. OnBackPressedDispatcher follows a chain of responsibility pattern to handle the callbacks. In other words, if you set your callback as enabled, only your callback will be executed. Otherwise, OnBackPressedDispatcher will ignore it and proceed to the next callback, and so on until it finds an enabled one (this might be useful when you have more than one callback, for instance). More info on this here.

So, in order to show your dialog, you would have to do something similar to this:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
  super.onViewCreated(view, savedInstanceState)

  val callback = object : OnBackPressedCallback(true /** true means that the callback is enabled */) {
    override fun handleOnBackPressed() {
        // Show your dialog and handle navigation
    }
  }

  // note that you could enable/disable the callback here as well by setting callback.isEnabled = true/false

  requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, callback)
}

As for the up button, it seems like (at least for now) there aren't many possibilities. The only option I could find up until now that uses the navigation component is to add a listener for the navigation itself, which would handle both buttons at the same time:

navController.addOnDestinationChangedListener { navController, destination ->
  if (destination.id == R.id.destination) {
    // do your thing
  }
}

Regardless, this has the caveat of allowing the activity or fragment where you add the listener to know about destinations it might not be supposed to.

Provide custom back navigation, All Android devices provide a Back button for this type of navigation, for use in fragments or other lifecycle owners that have a shorter lifetime  Back navigation is how users move backward through the history of screens they previously visited. All Android devices provide a Back button for this type of navigation, so you should not add a Back button to your app’s UI. Depending on the user’s Android device, this button might be a physical button or a software button.


With the navigation architecture components, you can do something like this:

  1. Tell your activity to dispatch all up clicks on the home button(back arrow) to anyone listening for it. This goes in your activity.
override fun onOptionsItemSelected(item: MenuItem): Boolean {
     if (item.itemId == android.R.id.home) {
         onBackPressedDispatcher.onBackPressed()
         return true
     }
     return super.onOptionsItemSelected(item)
}
  1. Then in your fragments, consume the events like so
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        requireActivity().onBackPressedDispatcher.addCallback(this) {
           if (*condition for showing dialog here*) {
               // Show dialog
           } else {
               // pop fragment by calling function below. Analogous to when the user presses the system UP button when the associated navigation host has focus.
               findNavController().navigateUp()
           }
        }
    }

Handling back button in Android Navigation Component, Show confirmation on back/up in Fragment with Navigation Architecture Component. I am using the Navigation Architecture Component for Android. For one of  Updated for navigation component v2.2.1 on April 5th, 2020. Recently I had a chance to try out the new Navigation Architecture Component library and wanted to share what I learned. I will walk you through applying the new navigation architecture to a Notes/todo app.


for up navigation simply override onOptionsItemSelected()

override fun onOptionsItemSelected(item: MenuItem): Boolean =
    when (item.itemId) {
        android.R.id.home -> {
            showDialog() // show your dialog here
            true
        }
        else -> super.onOptionsItemSelected(item)
}

How to add back button in fragment in android, Add next activity on click of back button open previous fragment but not show How to Set up your environment Note: The Navigation component requires Android Studio 3 The Navigation Architecture component is a part of the new AndroidX us the ability to handle the android back button to confirm before exit the App. The Navigation component's default NavHost implementation, NavHostFragment, handles swapping fragment destinations. Note: The Navigation component is designed for apps that have one main activity with multiple fragment destinations.


If you're using it with AppBarConfiguration, with the latest release there is now an AppBarConfiguration.OnNavigateUpListener. Refer to the below link for more information

https://developer.android.com/reference/androidx/navigation/ui/AppBarConfiguration.OnNavigateUpListener

Navigation Architecture Component for the Rest of Us, Recently I had a chance to try out the new Navigation Architecture default Fragment destination in our app (it will be the first screen shown It is implemented as a regular Fragment but in ideal world the Confirm Delete functionality we pop back stack (navigate back up the navigation hierarchy back to  Integrate the Navigation component. Once you're using a fragment-based architecture, you are ready to start integrating the Navigation component. First, add the most recent Navigation dependencies to your project, following the instructions in the Navigation library release notes. Create a navigation graph


Fragment Navigation Pattern in Android, As you navigate in the application there is an activity back stack maintained by the OS. A simple example is shown in the diagram below: Fragment image 1. Android architecture components are a collection of libraries that help you design robust, testable, and maintainable apps. Start with classes for managing your UI component lifecycle and handling data persistence. Learn the basics of putting together a robust app with the Guide to app architecture. Manage your app's lifecycle.


Conditional navigation and single event LiveData, Otherwise it would violate the responsibility that the new Architecture Activity Well since you are just adding the LoginFragment to the back stack, the in your device, you would infinitely get inside the loop of popping up this fragment. with live data and showing a simpler way for conditional navigation. The navigation graph for this example might look something like this: Figure 1: A login flow is handled independently from the app's main navigation flow. To authenticate, the app must navigate to the login_fragment, where the user can enter a username and password to authenticate. If accepted, the user is sent back to the profile_fragment screen


Routing & Navigation, Click the browser back button or the "Heroes" link instead. Up pops a dialog box. Confirm Dialog. You can say "OK" and lose your changes or click "Cancel" and  One of my favorite navigation pattern implementations is based on the “One-Activity-Multiple-Fragments” philosophy, or simply the Fragment Navigation Pattern, where every screen in the application is a full screen Fragment and all or most of these fragments are contained in one Activity.