Add predictive back animations

1. Before you begin

This codelab walks you through the process of adding predictive back animations to the SociaLite app. You add the back-to-home animation, default in-app animations, and create a custom in-app animation. Finally, you learn additional tips to help add predictive back animations to your app.

Prerequisites

  • Basic Kotlin knowledge
  • Basic Compose knowledge
  • Completion of the Set up Android Studio codelab, or familiarity with how to use Android Studio and test apps in an Android 15 emulator or on a physical device that runs Android 15
  • Optional: Completion of the Make your app edge to edge codelab

What you learn in this codelab

  • How to add the following predictive back animations:
  • Back-to-home
  • Default in-app animations
  • Custom in-app animations

What you need

  • The latest version of Android Studio.
  • An Android 15 Beta 2 or higher test device or emulator.
  • Gesture navigation enabled on the test device or emulator.

2. Get the starter code

  1. If you completed the Make your app edge-to-edge codelab, skip to the Add predictive back animations section because you already have the starter code.
  2. Download the starter code from GitHub, or clone the repository and check out the codelab_improve_android_experience_2024 branch.
$ git clone git@github.com:android/socialite.git
$ cd socialite
$ git checkout codelab_improve_android_experience_2024
  1. Open SociaLite in Android Studio, and run the app on your Android 15 device or emulator. You see a screen that looks like the following:

The Chats screen of the SocialLite app.

SociaLite with gesture navigation

This codelab is intended to be completed after the Make your app edge-to-edge codelab. If you haven't completed that codelab, before proceeding, at a minimum ensure that edge to edge is enabled in the MainActivity.kt file because in-app predictive back animations look best when your app is edge to edge.

If it is not there, add in enableEdgetoEdge() before setting the content in the MainActivity.kt file. Adding this line will allow you to proceed with the rest of this codelab, although you might see bottom UI occluded by the system navigation bars within a chat thread. To remove the bottom UI occlusion, see the Make your app edge to edge 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 {... }
    }
}

After going edge-to-edge, SociaLite looks like the following:

Gesture navigation in the SociaLite app. Gesture navigation

3. Add predictive back animations

What is predictive back?

Predictive back is a gesture-navigation feature that allows a user to preview the result of a back gesture before they fully complete it. It allows them to decide whether to continue to the previous view or stay in the current view.

Adding predictive back support to your Android app may help reinstate user confidence and deliver a more premium experience.

The back-to-home predictive back of the SocialLite app.

SociaLite with back-to-home predictive back

How to add predictive back support

Add the back-to-home predictive back animation

To see SociaLite without predictive back support for the back-to-home animation, follow these steps:

  1. Ensure that you're on the Chats page.
  2. Swipe back to return to system home. You're immediately taken back to the home screen without a preview of where the back swipe leads.

[add gif later]

SociaLite without the back-to-home animation

To add support for the back-to-home predictive back animation, set the android:enableOnBackInvokedCallback flag to true in the AndroidManifest.xml file.

// AndroidManifest.xml

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

To see how that one-line code change affected the back-swipe gesture in SociaLite, follow these steps:

  1. Ensure that you're on the Chats page.
  2. Slowly swipe back to return to system home.

You can see the back destination previewed behind the Chats page. This is what the back-to-home predictive back animation looks like.

The back-to-home predictive back of the SocialLite app.

SociaLite with back-to-home predictive back

Add default in-app animations

To see SociaLite without predictive back support for in-app animations, follow these steps:

  1. Ensure that you're on the Chats page.
  2. Select one of the conversations, such as Sheep.
  3. Slowly swipe back to return to the Chats page.

You see a cross-fade animation after completing the back gesture swipe and returning to the Chats page.

bb2701e3347841d0.gif

The SociaLite app without in-app predictive back animations.

To add more predictive back support to other parts of SociaLite, follow these steps

Upgrade the navigation compose dependency to androidx.navigation:navigation-compose:2.8.0-alpha07or later in the libs.versions.toml file.

// libs.versions.toml

[versions]
...
media3 = "1.2.0"
navigation = "2.8.0-alpha07"
...
  1. Press the 7c2b0d0d8c0fb2c5.png Sync project with Gradle files.
  2. Rerun SociaLite.
  3. Ensure that you're on the Chats page.
  4. Select one of the conversations, such as Sheep.
  5. Slowly swipe back to return to the Chats page. As you swipe back, you can see the Chats page fade into the view.

The SociaLite app with default in-app predictive back animations.

Default in-app animations

Add custom in-app animations

To create a custom predictive back in-app animation, follow these steps:

  1. Find NavHost in the ui/Main.kt file.
  2. Add popEnterTransition and popExitTransiton to scale and fade the incoming and outgoing screens.
// 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. Rerun SociaLite.
  2. Ensure that you're on the Chats page.
  3. Select one of the conversations, such as Sheep.
  4. Slowly swipe back to return to the Chats page. As you swipe back, the Sheep chat screen scales and fades out, and the Chats page scales and fades into the view.

The SociaLite app with custom in-app predictive back animations.

Custom in-app animations

The Navigation Compose library was able to run animations because of a migration from the Accompanist Navigation Animation library to the AndroidX library. By leveraging the Navigation Compose library and its built-in predictive back support, you were able to easily add support for predictive back gestures and improve the Android app experience.

Optional: Additional predictive back considerations

This is an optional section of tips that might pertain to your app.

Do not intercept back at the root (for example, MainActivity.kt)

If your app intercepts the back event with BackHandler, PredictiveBackHandler, OnBackPressedCallback or OnBackInvokedCallback at the root activity (for example, MainActivity.kt), your users will not see the predictive back-to-home animation.

Common use cases for intercepting back events at the root activity include event logging. We recommend logging events within the Fragment or Activity lifecycle methods instead of within OnBackPressedCallback or OnBackInvokedCallback for Views or within an addOnDestinationChangedListener or Compose. For more information, see Callback best practices.

Support for fragments

If you are using FragmentManager or the Navigation Component, predictive back is supported with the following fragment APIs using Animator, AndroidX Transitions and some Material Motions, like MaterialSharedAxis, MaterialFadeThrough, and MaterialFade:

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

Animation and Framework Transitions are not supported.

If your app is using another navigation library, check that library's documentation to see if they support predictive back animations.

Support for Material View Components

Predictive back animations are supported with Material View Components on devices that run Android 14 and higher when the android:enableOnBackInvokedCallback manifest flag is enabled and the compileSDK is API level 34 and higher. The supported Material View Components include search bar, bottom sheet, side sheet, and navigation drawer.

Support for Material Compose Components

Predictive back animations are supported with Material Compose Components. They include:

  • SearchBar
  • ModalBottomSheet
  • ModalNavigationDrawer/DismissibleNavigationDrawer

Ensure you're using androidx.compose.material3:material3-*:1.3.0-alpha01 dependency or above. The SearchBar and ModalBottomSheet automatically animate for predictive back when the android:enableOnBackInvokedCallback manifest flag is enabled. ModalNavigationDrawer/DismissibleNavigationDrawer requires the passing of drawerState into their respective sheet content composables.

Support for shared element transitions in Compose

Shared element transition with predictive back in Navigation Compose

Shared element transition with predictive back in Navigation Compose

To get support for predictive back, ensure you are using the navigation-compose 2.8.0-alpha06 dependency or above and add the android:enableOnBackInvokedCallback="true" flag to your AndroidManifest.xml file.

4. Get the solution code

The AndroidManifest.xml file should look like this:

// AndroidManifest.xml

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

NavHost in the ui/Main.kt file should look like this:

// 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,
)

And the libs.versions.toml file should look like this:

// libs.versions.toml

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

The solution code is available in the main branch.

To get the solution code, follow these steps:

  1. If you already downloaded SociaLite, run this command:

git checkout main

  1. If you didn't download SocialLite, download the code again to view the main branch:

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