添加预测性返回动画

1. 准备工作

此 Codelab 会引导您完成为 SociaLite 应用添加预测性返回动画的流程。您可添加“返回首页”动画、添加默认的应用内动画以及创建自定义的应用内动画。最后,您将学习更多有助于为应用添加预测性返回动画的提示。

前提条件

  • 具备 Kotlin 基础知识
  • 具备 Compose 基础知识
  • 已完成设置 Android Studio Codelab,或者熟悉如何在 Android 15 模拟器或搭载 Android 15 的实体设备中使用 Android Studio 并测试应用
  • 可选:完成打造无边框应用 Codelab

您将在此 Codelab 中学到的内容

  • 如何添加以下预测性返回动画:
  • 返回首页
  • 默认的应用内动画
  • 自定义的应用内动画

所需条件

  • 最新版本的 Android Studio。
  • 搭载 Android 15 Beta 2 或更高版本的测试设备或模拟器。
  • 测试设备或模拟器上已启用手势导航

2. 获取起始代码

  1. 如果您已完成打造无边框应用 Codelab,请跳至“添加预测性返回动画”部分,因为您已有起始代码。
  2. 从 GitHub 下载起始代码,或者克隆仓库并查看 codelab_improve_android_experience_2024 分支。
$ git clone git@github.com:android/socialite.git
$ cd socialite
$ git checkout codelab_improve_android_experience_2024
  1. 在 Android Studio 中打开 SociaLite,然后在搭载 Android 15 的设备或模拟器上运行该应用。您将看到如下所示的界面:

SocialLite 应用的“聊天”界面。

您应先完成打造无边框应用 Codelab,然后再学习此 Codelab。如果您尚未完成前述 Codelab,在继续操作之前,请至少确保在 MainActivity.kt 文件中启用无边框,因为当您的应用为无边框状态时,应用内预测性返回动画会呈现最佳效果。

如果没有相应选项,请先在 enableEdgetoEdge() 中添加,然后再在 MainActivity.kt 文件中设置内容。添加该行后,您可继续进行此 Codelab 的其余操作,但您可能会看到聊天会话中底部界面被系统导航栏遮挡。如需移除对底部界面的遮挡,请参阅打造无边框应用 Codelab。

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
   // Ensure to add this line if you haven't already completed the
   // Make your app edge-to-edge codelab.
        enableEdgeToEdge()
        super.onCreate(savedInstanceState)
        setContent {... }
    }
}

进入无边框状态后,SociaLite 将如下所示:

SociaLite 应用中的手势导航。

3. 添加“返回主页”预测性返回动画

什么是预测性返回?

预测性返回是一项手势导航功能,可让用户在彻底完成返回手势之前预览其结果。这样一来,用户就可以决定是继续访问上一个视图,还是留在当前视图中。

为 Android 应用添加预测性返回支持可能有助于恢复用户信心,并提供更优质的体验。

SocialLite 应用的“返回主屏幕”预测性返回。

如何添加预测性返回支持

如需查看不支持“返回主屏幕”动画预测性返回的 SocialLite,请按以下步骤操作:

  1. 确保您位于聊天页面中。
  2. 往回滑动即可返回到系统首页。您会立即返回到主屏幕,而不会预览返回滑动手势会打开的界面。

无“返回主屏幕”动画的 SocialLite 应用。

如需添加对“返回主屏幕”预测性返回动画的支持,请在 AndroidManifest.xml 文件中将 android:enableOnBackInvokedCallback 标志设置为 true

// AndroidManifest.xml

<application
  android:name=".SocialApp"
  ...
  android:enableOnBackInvokedCallback="true">
  <activity
    android:name=".MainActivity"
    android:exported="true"
    ...>

如需了解单行代码更改对 SociaLite 中的返回滑动手势造成的影响,请按以下步骤操作:

  1. 确保您位于聊天页面中。
  2. 慢慢地往回滑动即可返回到系统首页。

您可以看到在聊天页面之后预览的返回目标页面。这是“返回首页”预测性返回动画的显示效果。

SocialLite 应用的“返回主屏幕”预测性返回。

4. 添加应用内动画

默认的应用内动画

如需查看不支持应用内动画预测性返回的 SocialLite,请按以下步骤操作:

  1. 确保您位于聊天页面中。
  2. 选择其中一个对话,例如绵羊
  3. 慢慢地往回滑动即可返回到聊天页面。

完成返回手势滑动并返回到聊天页面后,您会看到一个交错淡出动画。

bb2701e3347841d0.gif

如需为 SociaLite 的其他部分添加更多预测性返回支持,请按以下步骤操作:

libs.versions.toml 文件中将 Navigation Compose 依赖项升级到 androidx.navigation:navigation-compose:2.8.0-alpha07 或更高版本。

// libs.versions.toml

[versions]
...
media3 = "1.2.0"
navigation = "2.8.0-alpha07"
...
  1. 7c2b0d0d8c0fb2c5.png Sync project with Gradle files
  2. 重新运行 SociaLite。
  3. 确保您位于聊天页面中。
  4. 选择其中一个对话,例如绵羊
  5. 慢慢地往回滑动返回到聊天页面。往回滑动时,您可看到聊天页面淡入视图中。这是默认的应用内动画。

有默认的应用内预测性返回动画的 SociaLite 应用。

自定义的应用内动画

如需创建自定义的预测性返回应用内动画,请按以下步骤操作:

  1. ui/Main.kt 文件中找到 NavHost
  2. 添加 popEnterTransitionpopExitTransition,以实现传入和传出界面的缩放及淡变。
// Main.kt
NavHost(
  navController = navController,
  startDestination = "home",
  popEnterTransition = {
    scaleIn(
      animationSpec = tween(
        durationMillis = 100,
        delayMillis = 35,
      ),
      initialScale = 1.1F,
     ) + fadeIn(
         animationSpec = tween(
           durationMillis = 100,
           delayMillis = 35,
         ),
     )
   },
  popExitTransition = {
     scaleOut(
       targetScale = 0.9F,
     ) + fadeOut(
         animationSpec = tween(
           durationMillis = 35,
           easing = CubicBezierEasing(0.1f, 0.1f, 0f, 1f),
         ),
     )
   },
  modifier = modifier,
)
  1. 重新运行 SociaLite。
  2. 确保您位于聊天页面中。
  3. 选择其中一个对话,例如绵羊
  4. 慢慢地往回滑动即可返回到聊天页面。当您往回滑动时,绵羊聊天页面会缩小并淡出,聊天页面则会放大并淡入视图中。

有自定义的应用内预测性返回动画的 SociaLite 应用。

Navigation Compose 库之所以能够运行动画,是得益于从 Accompanist Navigation Animation 库向 AndroidX 库的迁移。通过利用 Navigation Compose 库及其内置的预测性返回支持,您可以轻松添加对预测性返回手势的支持,并提升 Android 应用体验。

5. 选学:其他预测性返回注意事项

这是一个选学部分,可能包含一些与您的应用相关的提示。

勿在根目录(例如 MainActivity.kt)处拦截返回

如果您的应用使用 BackHandler, PredictiveBackHandler, OnBackPressedCallbackOnBackInvokedCallback 在根 activity 处(例如 MainActivity.kt)拦截返回事件,您的用户将不会看到预测性“返回首页”动画。

在根 activity 处拦截返回事件的常见用例包括事件日志记录。我们建议在 fragment 或 activity 生命周期方法中记录事件,而不是在 View 的 OnBackPressedCallbackOnBackInvokedCallback 中或者在 addOnDestinationChangedListener 或 Compose 中记录事件。如需了解详情,请参阅回调最佳实践

支持 fragment

如果您使用的是 FragmentManager 或 Navigation 组件,则预测性返回适用于以下使用 AnimatorAndroidX 过渡和一些 Material 运动(例如 MaterialSharedAxisMaterialFadeThroughMaterialFade)的 fragment API:

  • setCustomAnimations
  • setEnterTransition
  • setExitTransition
  • setReenterTransition
  • setReturnTransition
  • setSharedElementEnterTransition
  • setSharedElementReturnTransition

不支持动画框架过渡

如果您的应用使用的是其他导航库,请查看该库的文档,确认它是否支持预测性返回动画。

支持 Material View 组件

在搭载 Android 14 或更高版本的设备上,当已启用 android:enableOnBackInvokedCallback 清单标志且 compileSDK 是 API 级别 34 或更高时,预测性返回动画适用于 Material View 组件。支持的 Material View 组件包括搜索栏、底部动作条、侧边动作条和抽屉式导航栏。

支持 Material Compose 组件

Material Compose 组件支持预测性返回动画。它们包括:

  • SearchBar
  • ModalBottomSheet
  • ModalNavigationDrawer/DismissibleNavigationDrawer

确保您使用的是 androidx.compose.material3:material3-*:1.3.0-alpha01 依赖项或更高版本。启用 android:enableOnBackInvokedCallback 清单标志后,SearchBar 和 ModalBottomSheet 会自动为预测性返回添加动画效果。ModalNavigationDrawer/DismissibleNavigationDrawer 需要将 drawerState 传递到各自的动作条内容可组合函数中。

支持 Compose 中的共享元素过渡

Navigation Compose 中使用预测性返回功能的共享元素过渡

如需支持预测性返回,请确保您使用的是 navigation-compose 2.8.0-alpha06 依赖项或更高版本,并将 android:enableOnBackInvokedCallback="true" 标志添加到 AndroidManifest.xml 文件中。

6. 获取解决方案代码

AndroidManifest.xml 文件应如下所示:

// AndroidManifest.xml

<application
  android:name=".SocialApp"
  ...
  android:enableOnBackInvokedCallback="true">
  <activity
    android:name=".MainActivity"
    android:exported="true"
    ...>

ui/Main.kt 文件中的 NavHost 应如下所示:

// Main.kt
NavHost(
  navController = navController,
  startDestination = "home",
  popEnterTransition = {
    scaleIn(
      animationSpec = tween(
        durationMillis = 100,
        delayMillis = 35,
      ),
      initialScale = 1.1F,
     ) + fadeIn(
         animationSpec = tween(
           durationMillis = 100,
           delayMillis = 35,
         ),
     )
   },
  popExitTransition = {
     scaleOut(
       targetScale = 0.9F,
     ) + fadeOut(
         animationSpec = tween(
           durationMillis = 35,
           easing = CubicBezierEasing(0.1f, 0.1f, 0f, 1f),
         ),
     )
   },
  modifier = modifier,
)

libs.versions.toml 文件应如下所示:

// libs.versions.toml

[versions]
...
media3 = "1.2.0"
navigation = "2.8.0-alpha07"
...

可在 main 分支中获取解决方案代码。

如需获取解决方案代码,请按以下步骤操作:

  1. 如果您已下载 SociaLite,请运行以下命令:

git checkout main

  1. 如果您未下载 SocialLite,请再次下载代码以查看 main 分支:

git clone git@github.com:android/socialite.git

7. 了解更多内容

Android 开发者文档

Codelab