预测性返回是一项手势导航功能,可让用户预览返回滑动操作将其带到的位置。
例如,使用返回手势可以在应用后面显示主屏幕的动画预览,如图 1 中的模型所示。
从 Android 15 开始,预测性返回动画的开发者选项将不再可用。现在,对于完全或在 activity 级别选择启用预测性返回手势的应用,系统会显示“返回主屏幕”“跨任务”和“跨 activity”等系统动画。
您可以测试此返回主屏幕动画(如本页下一部分所述)。
如需支持预测性返回手势,您需要使用向后兼容的 OnBackPressedCallback
AppCompat 1.6.0-alpha05 (AndroidX) 或更高版本的 API 或使用新的 OnBackInvokedCallback
平台 API 更新应用。大多数应用都使用向后兼容的 AndroidX API。
此更新提供了一种迁移路径,可正确拦截返回导航,包括在 KeyEvent.KEYCODE_BACK
和任何使用 onBackPressed
方法的类(例如 Activity
和 Dialog
)中,将返回拦截替换成新的系统 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
实现自定义手势导航处理功能的新应用或现有应用,如提供自定义返回导航中所述。
如果您的应用属于此类别,请按照以下步骤添加对预测性返回手势的支持:
为了确保已在使用
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"
按照本页面中的说明选择启用预测性返回手势。
将包含不受支持的返回导航 API 的 AndroidX 应用迁移至 AndroidX API
如果您的应用使用 AndroidX 库,但会实现或引用不受支持的返回导航 API,则需要改用 AndroidX API 来支持新行为。
如需将不受支持的 API 迁移到 AndroidX API,请执行以下操作:
通过实现
OnBackPressedCallback
将系统返回导航处理逻辑迁移到 AndroidX 的OnBackPressedDispatcher
。如需获得详细指导,请参阅提供自定义返回导航。当已为停止拦截返回手势做好准备时,停用
OnBackPressedCallback
。停止通过
OnBackPressed
或KeyEvent.KEYCODE_BACK
拦截返回事件。请务必升级到 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"
成功迁移应用后,请选择启用预测性返回手势(如本页所述),以查看“返回主屏幕”系统动画。
将使用不受支持的返回导航 API 的应用迁移至平台 API
如果您的应用无法使用 AndroidX 库,而是使用不受支持的 API 实现或引用自定义返回导航,您必须迁移到 OnBackInvokedCallback
平台 API。
完成以下步骤,将不受支持的 API 迁移到平台 API:
在搭载 Android 13 或更高版本的设备上使用新的
OnBackInvokedCallback
API,并在搭载 Android 12 或更低版本的设备上依赖不受支持的 API。在
OnBackInvokedCallback
中向onBackInvokedDispatcher
注册您的自定义返回逻辑。这样可防止结束当前的 activity,让回调有机会在用户完成系统返回导航后响应返回操作。当已为停止拦截返回手势做好准备时,取消注册
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) */ } ); } }
对于 Android 13 及更高版本,停止通过
OnBackPressed
或KeyEvent.KEYCODE_BACK
拦截返回事件。成功迁移应用后,请选择启用预测性返回手势(如本页所述),以使
OnBackInvokedCallback
生效。
您可以向 PRIORITY_DEFAULT
或 PRIORITY_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
调用将继续有效。
在 activity 级别选择启用
从 Android 14 开始,您可以使用 android:enableOnBackInvokedCallback
标志在 activity 级别选择启用预测性系统动画。此行为有助于更轻松地管理将大型多 activity 应用迁移到预测性返回手势的过程。在 Android 15 中,预测性返回功能不再位于开发者选项背后。应用可以选择完全启用预测性返回,也可以在 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>
在前面的示例中,为 ".SecondActivity"
设置 android:enableOnBackInvokedCallback=true
会启用跨 activity 系统动画。
在使用 android:enableOnBackInvokedCallback
标志时,请注意以下事项:
- 设置
android:enableOnBackInvokedCallback=false
会在 activity 级别或应用级别关闭预测性返回动画(具体取决于您在哪个级别设置了标记),并指示系统忽略对OnBackInvokedCallback
平台 API 的调用。 不过,对OnBackPressedCallback
的调用会继续运行,因为OnBackPressedCallback
向后兼容,并会调用 Android 13 之前的版本不支持的onBackPressed
API。 - 在应用级别设置
enableOnBackInvokedCallback
标志会为应用中的所有 activity 建立默认值。您可以在 activity 级别设置标志来替换每个 activity 的默认值,如前面的代码示例所示。
回调最佳实践
使用 BackHandler
(适用于 Compose)、OnBackPressedCallback
或 OnBackInvokedCallback
等受支持的系统返回回调时,请遵循以下最佳实践。
确定用于启用和停用每个回调的界面状态
界面状态是描述界面的属性。我们建议您遵循以下简要步骤。
确定用于启用和停用每个回调的界面状态。
使用可观察数据容器类型(例如
StateFlow
或 Compose State)定义该状态,并在状态更改时启用或停用回调。
如果您的应用之前已将返回逻辑与条件语句相关联,这可能表示您在返回事件发生后对其进行了响应。避免在较新的回调中使用此模式。如果可能,请将回调移出条件语句,并改为将回调与可观察数据容器类型关联起来。
对界面逻辑使用系统返回回调
界面逻辑决定着如何显示界面。您可以使用系统返回回调运行界面逻辑,例如显示弹出式窗口或运行动画。
如果您的应用启用了系统返回回调,则预测性动画不会运行,并且您必须处理返回事件。请勿创建仅用于运行非界面逻辑的回调。
例如,如果拦截返回事件只是为了记录日志,请改为在 activity 或 fragment 生命周期内进行记录。
- 在 activity 到 activity 或 fragment 到 activity 的情况下,如果
onDestroy
中的isFinishing
为true
,请在 activity 生命周期内进行记录。 - 对于 fragment 到 fragment 的情况,如果
onDestroy
中的isRemoving
为 true,请在 fragment 的视图生命周期内进行记录。或者,使用FragmentManager.OnBackStackChangedListener
中的onBackStackChangeStarted
或onBackStackChangeCommitted
方法记录日志。
对于 Compose 用例,请在与 Compose 目的地关联的 ViewModel
的 onCleared()
回调中记录日志。这是了解 Compose 目的地何时从返回堆栈中弹出并被销毁的最佳信号。
创建单一责任回调
您可以向调度程序添加多个回调。这些回调将添加到堆栈中,其中最近添加的已启用回调会处理下一个返回手势,且每个返回手势对应一个回调。
如果回调只有一项职责,则更容易管理其启用状态。例如:
图 2 展示了如何在堆栈中设置多个回调,每个回调负责一项任务。只有当堆栈中位于其上方的回调处于停用状态时,回调才会运行。在此示例中,当用户在表单中输入数据时,系统会启用“确定要执行此操作吗?”回调;否则,系统会停用该回调。当用户滑回退出表单时,回调会打开一个确认对话框。
其他回调可以包括支持预测性返回的 Material 组件、使用 Progress API 的 AndroidX 转场效果,或其他自定义回调。
如果上述回调已停用且此 FragmentManager
的返回堆栈不为空(其中 childFragmentManager
附加在 fragment 中),则会运行 childFragmentManager
的回调。在此示例中,此内部回调已停用。
同样,如果上述回调已停用且其堆栈不为空,则 supportFragmentManager
的内部回调也会运行。无论是使用 FragmentManager
还是 NavigationComponent
进行导航,此行为都是一致的,因为 NavigationComponent
依赖于 FragmentManager
。在此示例中,如果用户未在表单中输入文本,导致“您确定...”回调函数被停用,那么系统会运行此回调函数。
最后,super.onBackPressed()
是系统级回调,如果上述回调被停用,系统会再次运行该回调。为了触发“返回主屏幕”“跨 activity”和“跨任务”等系统动画,supportFragmentManager
的返回堆栈必须为空,以便停用其内部回调。
测试预测性返回手势动画
如果您仍在使用 Android 13 或 Android 14,则可以测试图 1 中所示的返回主屏幕动画。
如需测试此动画,请完成以下步骤:
在您的设备上,依次转到设置 > 系统 > 开发者选项。
选择预测性返回手势动画。
启动更新后的应用,然后执行返回手势,看看实际运行效果。