添加对预测性返回手势的支持

图 1. 预测性返回手势在手机上的视觉效果和风格模拟

Android 13(API 级别 33)针对手机、大屏设备和可折叠设备等 Android 设备引入了预测性返回手势。该功能的发布历程跨度将达多年;完全实现后,该功能可让用户在完全完成某个返回手势之前就能预览此手势完成后的目的地或其他结果,以便用户能够决定是继续完成手势还是留在当前视图中。

例如,使用返回手势可以在应用后面显示主屏幕的动画预览,如图 1 中的模型所示。从 Android 13 开始,您可以通过启用一个开发者选项(如本页所述)来测试这种返回主屏幕动画

如需支持预测性返回手势,您需要使用向后兼容的 OnBackPressedCallback AppCompat 1.6.0-alpha05 (AndroidX) 或更高版本的 API,或使用新的 OnBackInvokedCallback 平台 API。大多数应用将使用向后兼容的 AndroidX API。

此更新提供了一种迁移路径,用于正确拦截返回导航,包括将 KeyEvent.KEYCODE_BACK 和任何具有 onBackPressed 方法的类(例如 ActivityDialog)所涉及的返回拦截替换成新的系统 Back API。

Codelab 和 Google I/O 大会视频

除了参考本页的文档外,您还可以试用我们的 Codelab, 其中提供了使用 AndroidX Activity API 处理预测性返回手势的常见 WebView 用例实现。

您还可以观看我们的 Google I/O 视频,其中介绍了实现 AndroidX 和平台 API 的其他示例。

更新使用默认返回导航的应用

如果您的应用未实现任何自定义返回行为(换言之,由系统处理返回导航),则更新应用以支持此功能非常简单。只需按照本页中的说明选择启用此功能即可。

如果您的应用使用 fragment 或 Navigation 组件,请也升级到 AndroidX Activity 1.6.0-alpha05 或更高版本。

更新使用自定义返回导航的应用

如果您的应用实现了自定义返回行为,则会有不同的迁移路径,具体取决于它是否使用了 AndroidX 以及它如何处理返回导航。

您的应用是否使用了 AndroidX 您的应用会如何处理返回导航 推荐的迁移路径(此页面上的链接)
AndroidX APIs 迁移现有的 AndroidX 返回实现
不受支持的平台 API 将包含不受支持的返回导航 API 的 AndroidX 应用迁移至 AndroidX API
不受支持的平台 API,可以迁移 将使用不受支持的返回导航 API 的应用迁移至平台 API
不受支持的平台 API,但无法迁移 推迟选择启用此功能,直到此功能成为必要功能为止

迁移 AndroidX 返回导航实现

此用例最常见(也最推荐)。它适用于使用 OnBackPressedDispatcher 实现自定义手势导航处理功能的新应用或现有应用,如提供自定义返回导航中所述。

如果您的应用属于此类别,请按照以下步骤添加对预测性返回手势的支持:

  1. 为了确保已在使用 OnBackPressedDispatcher API 的 API(例如 fragment 和 Navigation 组件)能够与预测性返回手势无缝配合使用,请升级到 AndroidX Activity 1.6.0-alpha05

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  2. 按照本页面中的说明选择启用预测性返回手势

将包含不受支持的返回导航 API 的 AndroidX 应用迁移至 AndroidX API

如果您的应用使用 AndroidX 库,但会实现或引用不受支持的返回导航 API,则需要改用 AndroidX API 来支持新行为。

如需将不受支持的 API 迁移到 AndroidX API,请执行以下操作:

  1. 通过实现 OnBackPressedCallback 将系统返回导航处理逻辑迁移到 AndroidX 的 OnBackPressedDispatcher。如需获得详细指导,请参阅提供自定义返回导航

  2. 当已为停止拦截返回手势做好准备时,停用 OnBackPressedCallback

  3. 停止通过 OnBackPressedKeyEvent.KEYCODE_BACK 拦截返回事件。

  4. 请务必升级到 AndroidX Activity 1.6.0-alpha05

    // In your build.gradle file:
    dependencies {
    
    // Add this in addition to your other dependencies
    implementation "androidx.activity:activity:1.6.0-alpha05"
    
  5. 成功迁移应用后,请采用预测性返回手势(如本页所述),以查看返回主屏幕的系统动画。

将使用不受支持的返回导航 API 的应用迁移至平台 API

如果您的应用无法使用 AndroidX 库,而是使用不受支持的 API 实现或引用自定义返回导航,您必须迁移到 OnBackInvokedCallback 平台 API。

完成以下步骤,将不受支持的 API 迁移到平台 API:

  1. 在搭载 Android 13 或更高版本的设备上使用新的 OnBackInvokedCallback API,并在搭载 Android 12 或更低版本的设备上依赖不受支持的 API。

  2. OnBackInvokedCallback 中向 onBackInvokedDispatcher 注册您的自定义返回逻辑。这样可防止当前 activity 完成,并且当用户完成系统返回导航后,您的回调有机会对返回操作做出响应。

  3. 当已为停止拦截返回手势做好准备时,取消注册 OnBackInvokedCallback。否则,使用系统的返回导航时,用户可能会看到不希望出现的行为,例如在视图之间“卡住”并被强制退出应用。

    以下示例展示了如何从 onBackPressed 迁移出逻辑:

    Kotlin

    @Override
    fun onCreate() {
        if (BuildCompat.isAtLeastT()) {
            onBackInvokedDispatcher.registerOnBackInvokedCallback(
                OnBackInvokedDispatcher.PRIORITY_DEFAULT
            ) {
                /**
                 * onBackPressed logic goes here. For instance:
                 * Prevents closing the app to go home screen when in the
                 * middle of entering data to a form
                 * or from accidentally leaving a fragment with a WebView in it
                 *
                 * Unregistering the callback to stop intercepting the back gesture:
                 * When the user transitions to the topmost screen (activity, fragment)
                 * in the BackStack, unregister the callback by using
                 * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
                 * (https://developer.android.com/reference/kotlin/android/window/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
                 */
            }
        }
    }
    

    Java

    @Override
    void onCreate() {
      if (BuildCompat.isAtLeastT()) {
        getOnBackInvokedDispatcher().registerOnBackInvokedCallback(
            OnBackInvokedDispatcher.PRIORITY_DEFAULT,
            () -> {
              /**
               * onBackPressed logic goes here - For instance:
               * Prevents closing the app to go home screen when in the
               * middle of entering data to a form
               * or from accidentally leaving a fragment with a WebView in it
               *
               * Unregistering the callback to stop intercepting the back gesture:
               * When the user transitions to the topmost screen (activity, fragment)
               * in the BackStack, unregister the callback by using
               * OnBackInvokeDispatcher.unregisterOnBackInvokedCallback
               * (https://developer.android.com/reference/kotlin/android/view/OnBackInvokedDispatcher#unregisteronbackinvokedcallback)
               */
            }
        );
      }
    }
    
  4. 对于 Android 13 及更高版本,停止通过 OnBackPressedKeyEvent.KEYCODE_BACK 拦截返回事件。

  5. 成功迁移应用后,请采用预测性返回手势(如本页所述),以使 OnBackInvokedCallback 生效。

采用预测性返回手势

根据具体情况确定如何更新应用后,就可以轻松地选择支持预测性返回手势。

如需采用预测性返回手势,请在 AndroidManifest.xml 中的 <application> 标记内将 android:enableOnBackInvokedCallback 标志设置为 true

<application
    ...
    android:enableOnBackInvokedCallback="true"
    ... >
...
</application>

如果您不指定值,则默认为 false 并执行以下操作:

  • 停用预测性返回手势系统动画。
  • 忽略 OnBackInvokedCallback,但 OnBackPressedCallback 调用将继续有效。

回调最佳实践

使用 BackHandler(适用于 Compose)、OnBackPressedCallbackOnBackInvokedCallback 等受支持的系统返回回调时,请遵循以下最佳实践;

确定用于启用和停用每个回调的界面状态

界面状态是描述界面的属性。我们建议您遵循以下简要步骤。

  1. 确定用于启用和停用每个回调的界面状态。

  2. 在整个流程中观察该状态,并在状态发生变化时启用或停用回调。

如果您的应用之前已将返回逻辑与条件语句相关联,这可能表示您在返回事件发生后,才对其做出回应 - 您应该避免使用这种模式来处理较新的回调。如果可能,请将回调移出条件语句,并改为将回调与状态流相关联。

对界面逻辑使用回调

界面逻辑决定着如何显示界面。对界面逻辑使用回调,例如,用于显示弹出式窗口或运行动画。

如果您的应用启用了回调,则预测性动画不会运行,并且您必须处理返回事件。请勿创建仅用于运行非界面逻辑的回调。

例如,如果拦截返回事件只是为了记录日志,请改为在 activity 或 fragment 生命周期内进行记录。

  • 在 activity 到 activity 或 fragment 到 activity 的情况下,如果 onDestroy 中的 isFinishingtrue,请在 activity 生命周期内进行记录。
  • 在 fragment 到 fragment 的情况下,如果 onDestroy 中的 isRemoving 为 true,则在 fragment 生命周期中进行记录;或者,使用 FragmentManager.OnBackStackChangedListener 中的 onBackStackChangeStartedonBackStackChangeCommitted 方法进行记录。

创建单一责任回调

之所以能够这么做,是因为您可以向调度程序添加多个回调。这些回调将添加到堆栈中,其中最近添加的已启用回调会处理下一个返回手势,且每个返回手势对应一个回调。

测试预测性返回手势动画

从 Android 13 最终版本开始,您应该能够启用一个开发者选项来测试图 1 中所示的返回主屏幕动画。

如需测试此动画,请完成以下步骤:

  1. 在您的设备上,依次转到设置 > 系统 > 开发者选项

  2. 选择预测性返回手势动画

  3. 启动更新后的应用,然后执行返回手势,看看实际运行效果。