ContentTransform

Class

Common
public class ContentTransform(
    public val targetContentEnter: EnterTransition,
    public val initialContentExit: ExitTransition,
    targetContentZIndex: Float = 0f,
    sizeTransform: SizeTransform? = SizeTransform(),
)

ContentTransform defines how the target content (i.e. content associated with target state) enters AnimatedContent and how the initial content disappears.

targetContentEnter defines the enter transition for the content associated with the new target state. It can be a combination of fadeIn, slideIn/slideInHorizontally /slideInVertically/AnimatedContentTransitionScope.slideIntoContainer, and expand. Similarly, initialContentExit supports a combination of ExitTransition for animating out the initial content (i.e. outgoing content). If the initial content and target content are of different size, the sizeTransform will be triggered unless it's explicitly set to null. AnimatedContentTransitionScope.slideIntoContainer and AnimatedContentTransitionScope.slideOutOfContainer can provide container-size-aware sliding in from the edge of the container, or sliding out to the edge of the container.

ContentTransform supports the zIndex definition when the content enters the AnimatedContent container via targetContentZIndex. By default, all content has a 0f zIndex. Among content with the same zIndex, the incoming target content will be on top, as it will be placed last. However, this may not always be desired. zIndex can be specified to change that order. The content with higher zIndex guarantee to be placed on top of content with lower zIndex.

sizeTransform manages the expanding and shrinking of the container if there is any size change as new content enters the AnimatedContent and old content leaves. Unlike AnimatedVisibility, for AnimatedContent it is generally more predictable to manage the size of the container using SizeTransform than influencing the size using expandIn/expandHorizontally/shrinkOut, etc for each content. By default, spring will be used to animate any size change, and AnimatedContent will be clipped to the animated size. Both can be customized by supplying a different SizeTransform. If no size animation is desired, sizeTransform can be set to null.

Code Examples

AnimatedContentTransitionSpecSample

@Suppress("UNUSED_VARIABLE")
fun AnimatedContentTransitionSpecSample() {
    // 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
                        }
                    }
                }
            )
    }
}