AnimatedContentTransitionScope


AnimatedContentTransitionScope provides functions that are convenient and only applicable in the context of AnimatedContent, such as slideIntoContainer and slideOutOfContainer.

Summary

Nested types

SlideDirection defines the direction of the slide in/out for slideIntoContainer and slideOutOfContainer.

Public functions

EnterTransition
slideIntoContainer(
    towards: AnimatedContentTransitionScope.SlideDirection,
    animationSpec: FiniteAnimationSpec<IntOffset>,
    initialOffset: (offsetForFullSlide: Int) -> Int
)

This defines a horizontal/vertical slide-in that is specific to AnimatedContent from the edge of the container.

Cmn
ExitTransition
slideOutOfContainer(
    towards: AnimatedContentTransitionScope.SlideDirection,
    animationSpec: FiniteAnimationSpec<IntOffset>,
    targetOffset: (offsetForFullSlide: Int) -> Int
)

This defines a horizontal/vertical exit transition to completely slide out of the AnimatedContent container.

Cmn
infix ContentTransform

Customizes the SizeTransform of a given ContentTransform.

Cmn

Public properties

open ExitTransition

KeepUntilTransitionsFinished defers the disposal of the exiting content till both enter and exit transitions have finished.

Cmn
Alignment

This returns the Alignment specified on AnimatedContent.

Cmn

Inherited functions

From androidx.compose.animation.core.Transition.Segment
open infix Boolean
S.isTransitioningTo(targetState: S)

Returns whether the provided state matches the initialState&& the provided targetState matches Segment.targetState.

Cmn

Inherited properties

From androidx.compose.animation.core.Transition.Segment
S

Initial state of a Transition Segment.

Cmn
S

Target state of a Transition Segment.

Cmn

Public functions

slideIntoContainer

fun slideIntoContainer(
    towards: AnimatedContentTransitionScope.SlideDirection,
    animationSpec: FiniteAnimationSpec<IntOffset> = spring(visibilityThreshold = IntOffset.VisibilityThreshold),
    initialOffset: (offsetForFullSlide: Int) -> Int = { it }
): EnterTransition

This defines a horizontal/vertical slide-in that is specific to AnimatedContent from the edge of the container. The offset amount is dynamically calculated based on the current size of the AnimatedContent and its content alignment. This offset (may be positive or negative based on the direction of the slide) is then passed to initialOffset. By default, initialOffset will be using the offset calculated from the system to slide the content in. slideIntoContainer is a convenient alternative to slideInHorizontally and slideInVertically when the incoming and outgoing content differ in size. Otherwise, it would be equivalent to slideInHorizontally and slideInVertically with an offset of the full width/height.

towards specifies the slide direction. Content can be slided into the container towards SlideDirection.Left, SlideDirection.Right, SlideDirection.Up and SlideDirection.Down.

animationSpec defines the animation that will be used to animate the slide-in.

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.togetherWith
import androidx.compose.ui.unit.sp

// enum class NestedMenuState { Level1, Level2, Level3 }
// This is an example of creating a transitionSpec for navigating in a nested menu. The goal
// is to 1) establish a z-order for different levels of the menu, and 2) imply a spatial
// order between the menus via the different slide direction when navigating to child menu vs
// parent menu. See the demos directory of the source code for a full demo.
val transitionSpec: AnimatedContentTransitionScope<NestedMenuState>.() -> ContentTransform = {
    if (initialState < targetState) {
            // Going from parent menu to child menu, slide towards left
            slideIntoContainer(towards = SlideDirection.Left) togetherWith
                // Keep exiting content in place while sliding in the incoming content.
                ExitTransition.KeepUntilTransitionsFinished
        } else {
            // Going from child menu to parent menu, slide towards right.
            // Slide parent by half amount compared to child menu to create an interesting
            // parallax visual effect.
            slideIntoContainer(towards = SlideDirection.Right) { offsetForFullSlide ->
                offsetForFullSlide / 2
            } togetherWith slideOutOfContainer(towards = SlideDirection.Right)
        }
        .apply {
            // Here we can specify the zIndex for the target (i.e. incoming) content.
            targetContentZIndex =
                when (targetState) {
                    NestedMenuState.Level1 -> 1f
                    NestedMenuState.Level2 -> 2f
                    NestedMenuState.Level3 -> 3f
                }
        }
}

slideOutOfContainer

fun slideOutOfContainer(
    towards: AnimatedContentTransitionScope.SlideDirection,
    animationSpec: FiniteAnimationSpec<IntOffset> = spring(visibilityThreshold = IntOffset.VisibilityThreshold),
    targetOffset: (offsetForFullSlide: Int) -> Int = { it }
): ExitTransition

This defines a horizontal/vertical exit transition to completely slide out of the AnimatedContent container. The offset amount is dynamically calculated based on the current size of the AnimatedContent and the new target size. This offset gets passed to targetOffset lambda. By default, targetOffset uses this offset as is, but it can be customized to slide a distance based on the offset. slideOutOfContainer is a convenient alternative to slideOutHorizontally and slideOutVertically when the incoming and outgoing content differ in size. Otherwise, it would be equivalent to slideOutHorizontally and slideOutVertically with an offset of the full width/height.

towards specifies the slide direction. Content can be slided out of the container towards SlideDirection.Left, SlideDirection.Right, SlideDirection.Up and SlideDirection.Down.

animationSpec defines the animation that will be used to animate the slide-out.

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.togetherWith
import androidx.compose.ui.unit.sp

// enum class NestedMenuState { Level1, Level2, Level3 }
// This is an example of creating a transitionSpec for navigating in a nested menu. The goal
// is to 1) establish a z-order for different levels of the menu, and 2) imply a spatial
// order between the menus via the different slide direction when navigating to child menu vs
// parent menu. See the demos directory of the source code for a full demo.
val transitionSpec: AnimatedContentTransitionScope<NestedMenuState>.() -> ContentTransform = {
    if (initialState < targetState) {
            // Going from parent menu to child menu, slide towards left
            slideIntoContainer(towards = SlideDirection.Left) togetherWith
                // Keep exiting content in place while sliding in the incoming content.
                ExitTransition.KeepUntilTransitionsFinished
        } else {
            // Going from child menu to parent menu, slide towards right.
            // Slide parent by half amount compared to child menu to create an interesting
            // parallax visual effect.
            slideIntoContainer(towards = SlideDirection.Right) { offsetForFullSlide ->
                offsetForFullSlide / 2
            } togetherWith slideOutOfContainer(towards = SlideDirection.Right)
        }
        .apply {
            // Here we can specify the zIndex for the target (i.e. incoming) content.
            targetContentZIndex =
                when (targetState) {
                    NestedMenuState.Level1 -> 1f
                    NestedMenuState.Level2 -> 2f
                    NestedMenuState.Level3 -> 3f
                }
        }
}
infix fun ContentTransform.using(sizeTransform: SizeTransform?): ContentTransform

Customizes the SizeTransform of a given ContentTransform. For example:

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.ui.unit.IntSize

// enum class CartState { Expanded, Collapsed }
val transitionSpec: AnimatedContentTransitionScope<CartState>.() -> ContentTransform = {
    // Fade in with a delay so that it starts after fade out
    fadeIn(animationSpec = tween(150, delayMillis = 150))
        .togetherWith(fadeOut(animationSpec = tween(150)))
        .using(
            SizeTransform { initialSize, targetSize ->
                // Using different SizeTransform for different state change
                if (CartState.Collapsed isTransitioningTo CartState.Expanded) {
                    keyframes {
                        durationMillis = 500
                        // Animate to full target width and by 200px in height at 150ms
                        IntSize(targetSize.width, initialSize.height + 200) at 150
                    }
                } else {
                    keyframes {
                        durationMillis = 500
                        // Animate 1/2 the height without changing the width at 150ms.
                        // The width and rest of the height will be animated in the
                        // timeframe between 150ms and duration (i.e. 500ms)
                        IntSize(
                            initialSize.width,
                            (initialSize.height + targetSize.height) / 2
                        ) at 150
                    }
                }
            }
        )
}

Public properties

KeepUntilTransitionsFinished

open val ExitTransition.Companion.KeepUntilTransitionsFinishedExitTransition

KeepUntilTransitionsFinished defers the disposal of the exiting content till both enter and exit transitions have finished. It can be combined with other ExitTransitions using +.

Important: KeepUntilTransitionsFinished works the best when the zIndex for the incoming and outgoing content are specified. Otherwise, if the content gets interrupted from entering and switching to exiting using KeepUntilTransitionsFinished, the holding pattern may render exiting content on top of the entering content, unless the z-order is specified.

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection
import androidx.compose.animation.ContentTransform
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.core.tween
import androidx.compose.animation.togetherWith
import androidx.compose.ui.unit.sp

// enum class NestedMenuState { Level1, Level2, Level3 }
// This is an example of creating a transitionSpec for navigating in a nested menu. The goal
// is to 1) establish a z-order for different levels of the menu, and 2) imply a spatial
// order between the menus via the different slide direction when navigating to child menu vs
// parent menu. See the demos directory of the source code for a full demo.
val transitionSpec: AnimatedContentTransitionScope<NestedMenuState>.() -> ContentTransform = {
    if (initialState < targetState) {
            // Going from parent menu to child menu, slide towards left
            slideIntoContainer(towards = SlideDirection.Left) togetherWith
                // Keep exiting content in place while sliding in the incoming content.
                ExitTransition.KeepUntilTransitionsFinished
        } else {
            // Going from child menu to parent menu, slide towards right.
            // Slide parent by half amount compared to child menu to create an interesting
            // parallax visual effect.
            slideIntoContainer(towards = SlideDirection.Right) { offsetForFullSlide ->
                offsetForFullSlide / 2
            } togetherWith slideOutOfContainer(towards = SlideDirection.Right)
        }
        .apply {
            // Here we can specify the zIndex for the target (i.e. incoming) content.
            targetContentZIndex =
                when (targetState) {
                    NestedMenuState.Level1 -> 1f
                    NestedMenuState.Level2 -> 2f
                    NestedMenuState.Level3 -> 3f
                }
        }
}

contentAlignment

val contentAlignmentAlignment

This returns the Alignment specified on AnimatedContent.