提供自定义返回导航

返回导航是用户在之前访问过的屏幕历史记录中向后移动的方式。所有 Android 设备都为此类导航提供了一个返回按钮,因此请勿在应用的 UI 中添加返回按钮。根据用户的 Android 设备,此按钮可能是物理按钮或软件按钮。

当用户在您的应用中导航时,Android 会维护一个返回栈。这使得 Android 能够在按下返回按钮时正确导航到以前的目的地。但是,在某些情况下,您的应用可能需要实现自己的返回行为以提供最佳的用户体验。

例如,当使用WebView时,您可能希望覆盖默认的返回按钮行为,以允许用户在 Web 浏览历史记录中向后导航,而不是应用中的先前屏幕。

Android 13 及更高版本包含 Android 设备的预测返回手势。要了解有关此功能的更多信息,请查看添加对预测返回手势的支持

实现自定义返回导航

ComponentActivityFragmentActivityAppCompatActivity 的基类,它允许您通过使用其 OnBackPressedDispatcher 来控制返回按钮的行为,您可以通过调用 getOnBackPressedDispatcher() 来检索它。

OnBackPressedDispatcher 控制返回按钮事件如何分派到一个或多个 OnBackPressedCallback 对象。 OnBackPressedCallback 的构造函数采用一个布尔值作为初始启用状态。当回调启用时,即 isEnabled() 返回 true,调度程序会调用回调的 handleOnBackPressed() 来处理返回按钮事件。您可以通过调用 setEnabled() 来更改启用状态。

回调是使用 addCallback 方法添加的。我们建议使用 addCallback() 方法,该方法采用 LifecycleOwner。这确保 OnBackPressedCallback 仅在 LifecycleOwnerLifecycle.State.STARTED 时添加。活动还在其关联的 LifecycleOwner 被销毁时删除已注册的回调,这可以防止内存泄漏,并使 LifecycleOwner 适用于片段或比活动生命周期更短的其他生命周期所有者。

这是一个回调实现示例

Kotlin

class MyFragment : Fragment() {

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

        // This callback is only called when MyFragment is at least started
        val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
            // Handle the back button event
        }

        // The callback can be enabled or disabled here or in the lambda
    }
    ...
}

Java

public class MyFragment extends Fragment {

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

        // This callback is only called when MyFragment is at least started
        OnBackPressedCallback callback = new OnBackPressedCallback(true /* enabled by default */) {
            @Override
            public void handleOnBackPressed() {
                // Handle the back button event
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(this, callback);

        // The callback can be enabled or disabled here or in handleOnBackPressed()
    }
    ...
}

您可以使用 addCallback() 提供多个回调。当您这样做时,回调会按照您添加它们的相反顺序调用 - 最后添加的回调首先有机会处理返回按钮事件。例如,如果您按顺序添加了三个名为 onetwothree 的回调,则它们的调用顺序为 threetwoone

回调遵循责任链模式。链中的每个回调仅在前面的回调未启用时才被调用。这意味着,在前面的示例中,仅当回调 three 未启用时才调用回调 two,并且仅当回调 two 未启用时才调用回调 one

请注意,当使用addCallback()添加回调时,只有当LifecycleOwner进入Lifecycle.State.STARTED状态后,它才会被添加到责任链中。

我们建议在OnBackPressedCallback上更改启用状态以进行临时更改,因为这样做可以保持上面描述的顺序。如果您在多个嵌套的生命周期所有者上注册了回调,这一点尤其重要。

在您希望完全移除OnBackPressedCallback的情况下,您可以调用remove()。这通常没有必要,因为当关联的LifecycleOwner销毁时,回调会自动移除。

Activity onBackPressed()

如果您正在使用onBackPressed()处理后退按钮事件,我们建议您改为使用OnBackPressedCallback。但是,如果您无法进行此更改,则以下规则适用

  • 当您调用super.onBackPressed()时,将评估通过addCallback注册的所有回调。
  • 在 Android 12(API 级别 32)及更低版本中,无论是否注册了任何OnBackPressedCallback实例,都会始终调用onBackPressed