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

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

预测性返回是一项手势导航功能,可让用户预览向后滑动时即将前往的位置。

例如,使用返回手势可以在应用后面显示主屏幕的动画预览,如图 1 中的模型所示。

从 Android 15 开始,预测性返回动画的开发者选项不再可用。现在,如果应用已选择完全启用或在 activity 级别启用预测性返回手势,则会显示“返回主屏幕”、跨任务和跨 activity 等系统动画。

您可以测试这种返回主屏幕动画(如本页的下一部分所述)。

如需支持预测性返回手势,您需要使用向后兼容的 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 的其他示例。

在 Compose 中处理自定义返回手势

Compose 提供了 PredictiveBackHandler 可组合项来处理自定义返回手势。此 API 可让您响应返回手势,并提供一个 FlowBackEventCompat 对象,您可以使用这些对象在用户滑动时实现自定义动画或过渡效果。

PredictiveBackHandler(enabled = isBackHandlerEnabled) { progress: Flow<BackEventCompat> ->
    try {
        progress.collect { backEvent ->
            // Update your UI or animation based on backEvent.progress
        }
        // Handle the final back action (e.g., navigate back)
    } catch (e: CancellationException) {
        // Back gesture was cancelled, reset your UI
    }
}

如果您只需要拦截返回手势,而无需跟踪进度,请使用 BackHandler

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

预测性返回功能默认处于启用状态。

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

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

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

您的应用会如何处理返回导航 推荐的迁移路径(此页面上的链接)
AndroidX APIs 迁移现有的 AndroidX 返回实现
不受支持的平台 API 将包含不受支持的返回导航 API 的 AndroidX 应用迁移至 AndroidX API

迁移 AndroidX 返回导航实现

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

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

```xml
// In your build.gradle file:
dependencies {

// Add this in addition to your other dependencies
implementation "androidx.activity:activity:1.6.0-alpha05"
```

将包含不受支持的返回导航 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"
    

选择停用预测性返回

如需选择停用预测性返回手势,请在 AndroidManifest.xml<application> 标记中将 android:enableOnBackInvokedCallback 标志设置为 false

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

如果将此属性设置为 false,则会执行以下操作:

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

在 activity 级别选择停用

您可以使用 android:enableOnBackInvokedCallback 标志在 activity 级别选择停用预测性系统动画。此行为有助于更轻松地管理将大型多 activity 应用迁移到预测性返回手势的过程。

以下代码展示了将 enableOnBackInvokedCallback 设置为从 MainActivity 启用“返回主屏幕”系统动画的示例:

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

        <activity
            android:name=".MainActivity"
            android:enableOnBackInvokedCallback="true"
            ...
        </activity>
        <activity
            android:name=".SecondActivity"
            android:enableOnBackInvokedCallback="false"
            ...
        </activity>
    </application>
</manifest>

在使用 android:enableOnBackInvokedCallback 标志时,请注意以下事项:

  • 设置 android:enableOnBackInvokedCallback=false 会在 activity 级别或应用级别关闭预测性返回动画(具体取决于您在哪个级别设置了标记),并指示系统忽略对 OnBackInvokedCallback 平台 API 的调用。不过,对 OnBackPressedCallback 的调用会继续运行,因为 OnBackPressedCallback 向后兼容,并会调用 Android 13 之前的版本不支持的 onBackPressed API。
  • 在应用级别设置 enableOnBackInvokedCallback 标志会为应用中的所有 activity 建立默认值。您可以在 activity 级别设置标志来替换每个 activity 的默认值,如前面的代码示例所示。

回调最佳实践

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

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

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

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

  2. 使用可观察数据容器类型(例如 StateFlow 或 Compose State)定义该状态,并在状态更改时启用或停用回调。

如果您的应用之前已将返回逻辑与条件语句相关联,这可能表示您是在返回事件发生后才做出回应。请避免使用这种模式,而改用较新的回调。 如果可能,请将回调移出条件语句,并改为将回调与可观察数据容器类型关联起来。

对界面逻辑使用系统返回回调

界面逻辑决定着如何显示界面。您可以使用系统返回回调运行界面逻辑,例如显示对话框或运行动画。

如果您的应用启用了 OnBackPressedCallbackOnBackInvokedCallback 并搭配 PRIORITY_DEFAULTPRIORITY_OVERLAY,则预测性返回动画不会运行,并且您必须处理返回事件。请勿创建这些回调来运行业务逻辑或进行日志记录。

如果您的应用必须在用户向后滑动时运行业务逻辑或记录日志,请使用以下方法:

  • 在搭载 Android 16 及更高版本的设备上,将 OnBackInvokedCallbackPRIORITY_SYSTEM_NAVIGATION_OBSERVER 搭配使用。这会创建一个不消耗返回事件的观察者回调。例如,您可以在用户从根 activity 向后滑动时(换句话说,在用户离开您的应用时)注册此回调。在这种情况下,您可以记录返回事件或运行其他业务逻辑,并且返回首页动画仍会播放。
  • 在 activity 到 activity 或 fragment 到 activity 的情况下,如果 onDestroy 中的 isFinishingtrue,请在 activity 生命周期内进行记录。
  • 在 fragment 到 fragment 的情况下,如果 onDestroy 中的 isRemoving 为 true,请在 fragment 的视图生命周期中进行记录。或者,使用 FragmentManager.OnBackStackChangedListener 中的 onBackStackChangeStartedonBackStackChangeCommitted 方法进行记录。
  • 对于 Compose 场景,请在与 Compose 目的地相关联的 ViewModelonCleared() 回调中记录日志。这是用于了解 Compose 目的地何时从返回堆栈中弹出并销毁的最佳信号。

创建单一责任回调

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

如果回调具有单一职责,则更容易管理回调的启用状态。例如:

堆栈中回调的顺序。
图 2. 回调堆栈图。

图 2 显示了堆栈中可以有多个回调,每个回调负责一项任务。只有当堆栈中位于其上方的回调处于停用状态时,回调才会运行。在此示例中,当用户在表单中输入数据时,系统会启用“您确定要...吗?”回调,否则会停用该回调。 当用户向后滑动以退出表单时,该回调会打开一个确认对话框。

另一个回调可以包含支持预测性返回的 Material 组件、使用 Progress API 的 AndroidX 转场效果或其他自定义回调。

相同的堆栈行为也适用于 Compose:最内层的 PredictiveBackHandlerBackHandler 具有优先权。

同样,如果上述回调被停用,且相应 FragmentManager 的返回堆栈不为空,则会运行 childFragmentManager 的回调。在此示例中,此内部回调已停用。

同样,如果上述回调被停用,且 supportFragmentManager 的堆栈不为空,则 supportFragmentManager 的内部回调会运行。在此示例中,如果用户未在表单中输入文本,导致“您确定要...”回调被停用,则系统会运行此回调。

最后,如果上述回调被停用,系统会处理返回手势。为了触发系统动画(例如“返回主屏幕”、跨 activity 和跨任务),supportFragmentManager 的返回堆栈必须为空,以便其内部回调处于停用状态。

测试预测性返回手势动画

如果您仍在使用 Android 13 或 Android 14,可以测试图 1 中所示的返回主屏幕动画。

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

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

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

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