CapturedAnimatedVisibility

Functions summary

Unit
@Composable
CapturedAnimatedVisibility(
    visible: Boolean,
    modifier: Modifier,
    enter: EnterTransition,
    exit: ExitTransition,
    label: String,
    content: @Composable () -> Unit
)

CapturedAnimatedVisibility animates the appearance and disappearance of its content as visible changes.

Cmn
Unit
@Composable
CapturedAnimatedVisibility(
    visibleState: MutableTransitionState<Boolean>,
    modifier: Modifier,
    enter: EnterTransition,
    exit: ExitTransition,
    label: String,
    content: @Composable () -> Unit
)

Animates the appearance and disappearance of its content as visibleState's target state changes.

Cmn

Functions

CapturedAnimatedVisibility

@Composable
fun CapturedAnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandIn(),
    exit: ExitTransition = shrinkOut() + fadeOut(),
    label: String = "CapturedAnimatedVisibility",
    content: @Composable () -> Unit
): Unit

CapturedAnimatedVisibility animates the appearance and disappearance of its content as visible changes. Unlike AnimatedVisibility, when visible becomes false the child composition is removed immediately and the exit transition animates the last captured frame of the content via a graphics layer. This means the caller does not need to retain any data for the content once visible is false.

CapturedAnimatedVisibility is designed for content removal animations where there is a need to immediately release resources or a desire to no longer maintain data or states during exit. Since CapturedAnimatedVisibility displays a layer that captured the rendering of the content, it will also not respond to any gestures. In contrast, content in AnimatedVisibility remains live in composition during exit, responding to touch input and continuing internal animations (e.g. shared element or infinite animations) until the exit animation finishes and the content is removed from composition.

Because the content is no longer live during exit, no AnimatedVisibilityScope is provided to the content lambda.

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.CapturedAnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

var visible by remember { mutableStateOf(true) }
Column {
    Button(onClick = { visible = !visible }) { Text(if (visible) "Hide" else "Show") }
    Spacer(Modifier.height(16.dp))
    CapturedAnimatedVisibility(
        visible = visible,
        enter = fadeIn() + expandVertically(),
        exit = fadeOut() + shrinkVertically(),
    ) {
        // Child composition is removed immediately when visible becomes false
        Box(Modifier.size(100.dp).background(Color.Blue, shape = RoundedCornerShape(8.dp)))
    }
}
Parameters
visible: Boolean

controls whether the content should be visible

modifier: Modifier = Modifier

Modifier for the layout

enter: EnterTransition = fadeIn() + expandIn()

EnterTransition used for the appearing animation

exit: ExitTransition = shrinkOut() + fadeOut()

ExitTransition applied to the last captured frame when disappearing

label: String = "CapturedAnimatedVisibility"

label to differentiate from other animations in Android Studio Animation Preview

content: @Composable () -> Unit

content to appear or disappear based on visible

CapturedAnimatedVisibility

@Composable
fun CapturedAnimatedVisibility(
    visibleState: MutableTransitionState<Boolean>,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandIn(),
    exit: ExitTransition = shrinkOut() + fadeOut(),
    label: String = "CapturedAnimatedVisibility",
    content: @Composable () -> Unit
): Unit

Animates the appearance and disappearance of its content as visibleState's target state changes.

Using a MutableTransitionState allows observing the state of the animation (e.g. MutableTransitionState.currentState, * MutableTransitionState.targetState, and MutableTransitionState.isIdle) as well as setting an initial visibility state that is different than the MutableTransitionState.targetState to animate content upon entering composition.

Unlike AnimatedVisibility, when visibleState's targetState becomes false the child composition is removed immediately in CapturedAnimatedVisibility. The exit transition animates the last captured frame of the content via a graphics layer.

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.CapturedAnimatedVisibility
import androidx.compose.animation.core.MutableTransitionState
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

// MutableTransitionState allows observing the animation status (currentState, targetState, and
// isIdle) as well as setting an initial currentState = false and targetState = true to animate
// in immediately upon entering composition.
val visibleState = remember { MutableTransitionState(false) }.apply { targetState = true }

Column {
    Button(onClick = { visibleState.targetState = !visibleState.targetState }) {
        Text(if (visibleState.targetState) "Hide" else "Show")
    }
    Spacer(Modifier.height(8.dp))
    // Observe the current animation status directly via visibleState properties
    Text(
        "State: current=${visibleState.currentState}, " +
            "target=${visibleState.targetState}, " +
            "isIdle=${visibleState.isIdle}"
    )
    Spacer(Modifier.height(16.dp))
    CapturedAnimatedVisibility(
        visibleState = visibleState,
        enter = fadeIn() + expandVertically(),
        exit = fadeOut() + shrinkVertically(),
    ) {
        // Content animates IN from false -> true upon initial composition.
        // When targetState becomes false, child composition is removed immediately
        // while the last captured graphics layer frame animates OUT.
        Box(Modifier.size(100.dp).background(Color.Red, shape = RoundedCornerShape(8.dp)))
    }
}
Parameters
visibleState: MutableTransitionState<Boolean>

MutableTransitionState controlling visibility and allowing animation state observation

modifier: Modifier = Modifier

Modifier for the layout

enter: EnterTransition = fadeIn() + expandIn()

EnterTransition used for the appearing animation

exit: ExitTransition = shrinkOut() + fadeOut()

ExitTransition applied to the last captured frame when disappearing

label: String = "CapturedAnimatedVisibility"

label to differentiate from other animations in Android Studio Animation Preview

content: @Composable () -> Unit

content to appear or disappear based on visibleState