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

图 1. 手机上预测式返回手势外观和感觉的模型图

预测式返回是一种手势导航功能,使用户可以预览向后滑动将他们带到哪里。

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

从 Android 15 开始,预测式返回动画的开发者选项不再可用。对于已完全或在活动级别选择加入预测式返回手势的应用,现在会显示系统动画,例如返回主页、跨任务和跨活动动画。

您可以测试此返回主页动画(如本页后面部分所述)。

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

此更新提供了一条迁移路径,以便正确拦截返回导航,这包括用新的系统返回 API 替换来自KeyEvent.KEYCODE_BACK 和任何具有onBackPressed 方法的类(例如ActivityDialog)的返回拦截。

Codelab 和 Google I/O 视频

除了使用此页面上的文档外,还可以试用我们的 codelab。它提供了一个 WebView 的常见用例实现,该实现使用 AndroidX Activity API 处理预测式返回手势。

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

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

如果您的应用没有实现任何自定义返回行为(换句话说,它将返回处理留给系统),那么更新您的应用以支持此功能非常简单。如本指南中所述,选择加入此功能

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

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

如果您的应用实现自定义返回行为,则根据它是否使用 AndroidX 以及如何处理返回导航,将存在不同的迁移路径。

您的应用使用 AndroidX 您的应用如何处理返回导航 推荐迁移路径(本页链接)
AndroidX API 迁移现有的 AndroidX 返回实现
不受支持的平台 API 将包含不受支持的返回导航 API 的 AndroidX 应用迁移到 AndroidX API
不受支持的平台 API,可以迁移 将使用不受支持的返回导航 API 的应用迁移到平台 API
不受支持的平台 API,但无法迁移 推迟选择加入 直到这成为必需的功能

迁移 AndroidX 返回导航实现

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

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

  1. 为了确保已使用OnBackPressedDispatcher API(例如片段和导航组件)的 API 与预测式返回手势无缝协同工作,请升级到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. 将您的系统返回处理逻辑迁移到 AndroidX 的OnBackPressedDispatcher,并实现OnBackPressedCallback。有关详细指导,请参阅提供自定义返回导航

  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. 使用onBackInvokedDispatcherOnBackInvokedCallback 中注册您的自定义返回逻辑。这可以防止当前活动结束,并且您的回调有机会在用户完成系统返回导航后对返回操作做出反应。

  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 生效。

您可以使用PRIORITY_DEFAULTPRIORITY_OVERLAY 注册OnBackInvokedCallback,这在类似的 AndroidX OnBackPressedCallback 中不可用。在某些情况下,使用PRIORITY_OVERLAY 注册回调很有帮助。

当您从onKeyPreIme() 迁移并且您的回调需要接收返回手势而不是打开的 IME 时,此方法适用。IME 在打开时使用PRIORITY_DEFAULT 注册回调。使用PRIORITY_OVERLAY 注册您的回调,以确保OnBackInvokedDispatcher 将返回手势分派给您的回调,而不是打开的 IME。

启用预测式返回手势

确定如何根据您的情况更新应用后,请启用对预测式返回手势的支持。

要启用此功能,请在AndroidManifest.xml 中的<application> 标签中,将android:enableOnBackInvokedCallback 标志设置为true

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

如果您未提供值,则默认为false,并执行以下操作:

  • 禁用预测式返回手势系统动画。
  • 忽略OnBackInvokedCallback,但OnBackPressedCallback 调用将继续工作。

在活动级别启用

从 Android 14 开始,android:enableOnBackInvokedCallback 标志允许您在活动级别启用预测式系统动画。此行为使大型多活动应用迁移到预测式返回手势更易于管理。在 Android 15 中,预测式返回不再位于开发者选项之后。应用可以完全启用预测式返回或在活动级别启用。

以下代码显示了如何使用enableOnBackInvokedCallbackMainActivity 启用返回主屏幕的系统动画。

<manifest ...>
    <application . . .

        android:enableOnBackInvokedCallback="false">

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

在前面的示例中,为".SecondActivity" 设置android:enableOnBackInvokedCallback=true 将启用跨活动系统动画。

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

  • 设置android:enableOnBackInvokedCallback=false 将关闭活动级别或应用级别的预测式返回动画(取决于您设置标签的位置),并指示系统忽略对OnBackInvokedCallback 平台 API 的调用。但是,对OnBackPressedCallback 的调用将继续运行,因为OnBackPressedCallback 向后兼容并调用onBackPressed API,该 API 在 Android 13 之前不受支持。
  • 在应用级别设置enableOnBackInvokedCallback 标志将为应用中的所有活动建立默认值。您可以通过在活动级别设置标志来覆盖每个活动的默认值,如前面的代码示例所示。

回调最佳实践

以下是使用受支持的系统返回回调的最佳实践;BackHandler(用于 Compose)、OnBackPressedCallbackOnBackInvokedCallback

确定启用和禁用每个回调的 UI 状态

UI 状态是描述 UI 的属性。我们建议遵循以下高级步骤。

  1. 确定启用和禁用每个回调的 UI 状态。

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

如果您的应用以前将返回逻辑与条件语句相关联,这可能表示您在返回事件发生后才做出反应。使用较新的回调避免这种模式。如果可能,请将回调移到条件语句之外,而是将回调与可观察数据持有者类型相关联。

将系统返回回调用于 UI 逻辑

UI 逻辑决定如何显示 UI。使用系统返回回调来运行 UI 逻辑,例如显示弹出窗口或运行动画。

如果您的应用启用了系统返回回调,则预测式动画不会运行,您必须处理返回事件。不要仅为运行非 UI 逻辑而创建回调。

例如,如果您只是为了记录而拦截返回事件,请改为在 Activity 或 Fragment 生命周期内进行记录。

  • 对于活动到活动的情况或片段到活动的情况,如果 Activity 生命周期内的onDestroy 中的isFinishingtrue,则进行记录。
  • 对于片段到片段的情况,如果片段视图生命周期内的onDestroy 中的isRemoving 为 true,则进行记录。或者使用onBackStackChangeStartedonBackStackChangeCommitted 方法在FragmentManager.OnBackStackChangedListener 中进行记录。

对于 Compose 的情况,请在与 Compose 目标关联的ViewModelonCleared() 回调中进行记录。这是了解 Compose 目标何时从返回堆栈中弹出并销毁的最佳信号。

创建单一职责回调

您可以向调度程序添加多个回调。回调被添加到堆栈中,其中最后添加的已启用回调将使用每个返回手势一个回调来处理下一个返回手势。

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

Ordering of callbacks in a stack.
图 2. 回调堆栈图。

图 2 显示了如何在堆栈中有多个回调,每个回调负责一件事情。只有当堆栈中高于它的回调被禁用时,回调才会运行。在此示例中,“确定吗?”回调在用户将数据输入表单时启用,否则禁用。当用户向后滑动退出表单时,该回调将打开一个确认对话框。

其他回调可以包含支持预测式返回的 Material 组件、使用 Progress API 的 AndroidX 过渡或其他自定义回调。

childFragmentManager 的回调将在上述回调被禁用且此FragmentManager 的返回堆栈不为空时运行,其中childFragmentManager 附加在 Fragment 内。在此示例中,此内部回调被禁用。

同样,如果上述回调被禁用且其堆栈不为空,则supportFragmentManager 的内部回调将运行。当使用FragmentManagerNavigationComponent 进行导航时,此行为是一致的,因为NavigationComponent 依赖于FragmentManager。在此示例中,如果用户没有在表单中输入文本导致“确定吗?”回调被禁用,则此回调将运行。

最后,super.onBackPressed() 是系统级回调,如果上述回调被禁用,则再次运行。为了触发系统动画(例如返回主屏幕、跨活动和跨任务),supportFragmentManager 的返回堆栈必须为空,因此其内部回调被禁用。

测试预测式返回手势动画

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

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

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

  2. 选择预测式返回动画

  3. 启动更新后的应用,并使用返回手势查看其运行情况。