Provide custom back navigation

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.

Android maintains a back stack of destinations as the user navigates throughout your application. This usually allows Android to properly navigate to previous destinations when the Back button is pressed. However, there are a few cases where your app might need to implement your own Back behavior in order to provide the best possible user experience. For example, when using a WebView, you might want to override default Back button behavior to allow the user to navigate back through their web browsing history instead of previous screens in your app.

Implement Custom Back Navigation

To provide custom back button behavior, implement OnBackPressedCallback, and register this callback with your activity by calling addOnBackPressedCallback(). OnBackPressedCallback defines a single method, handleOnBackPressed(), which responds to a back press event. This method must return a Boolean value indicating whether the event was successfully processed.

A LifecycleOwner is passed as the first argument to addOnBackPressedCallback. Since OnBackPressedCallback can be registered from any fragment attached to the activity (each with its own lifecycle), this allows the activity to manage all registered callbacks effectively and ensures that the provided callback is invoked only if its LifecycleOwner is at least Lifecycle.State.STARTED. The activity also removes registered callbacks when their associated LifecycleOwner is destroyed, which prevents memory leaks.

An overloaded version of addOnBackPressedCallback() is also available, which uses the hosting activity as the lifecycle owner. This overload is suitable if your OnBackPressedCallback should exist for the entire lifecycle of the activity or if you are manually calling removeOnBackPressedCallback().

Here's an example callback implementation:

Kotlin

class MyFragment : Fragment() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // This callback will only be called when MyFragment is at least Started.
        requireActivity().addOnBackPressedCallback(this) {
            ...
            true // return true if event was handled
        }
    }
    ...
}

Java

public class MyFragment extends Fragment {

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // This callback will only be called when MyFragment is at least Started.
        requireActivity().addOnBackPressedCallback(this, new OnBackPressedCallback() {
            @Override
            public boolean handleOnBackPressed() {
                ...
                return true; // return true if event was handled
            }
        });
    }
    ...
}

You can provide multiple callbacks via addOnBackPressedCallback(). When doing so, the callbacks are invoked in the reverse order in which they are passed. For example, if you registered three callbacks named one, two and three in order, they would be invoked in the order of three,two, and one, respectively.

Callbacks follow the Chain of Responsibility pattern. Each subsequent callback in the chain is invoked only if the preceding callback was not able to process the event. This means that in the preceding example, callback one would be invoked only if callback two returned false. Callback two would only be invoked if callback three returned false, and so on.

You can remove a callback at any time by calling removeOnBackPressedCallback(). This is usually not necessary, however, because callbacks are automatically removed when their associated LifecycleOwner is destroyed.

Activity onBackPressed()

If you are using onBackPressed() to handle back button behavior, we recommend moving to the lifecycle-aware OnBackPressedCallback. However, if you are unable to make this change, the following rules apply:

  • All callbacks registered via onBackPressedCallback are evaluated when you call super.onBackPressed().
  • onBackPressed is always called, regardless of any registered instances of OnBackPressedCallback.