Saltar a contenido

8.1 Animaciones

Una animación comunica que algo ha cambiado. Compose la hace sencilla: cambias el estado y le dices que el cambio sea gradual.

Aparecer y desaparecer

var visible by remember { mutableStateOf(true) }

Button(onClick = { visible = !visible }) { Text("Alternar") }
AnimatedVisibility(visible = visible, enter = fadeIn() + expandVertically(), exit = fadeOut() + shrinkVertically()) {
    Text("Ahora me ves")
}

Animar un valor

animate*AsState transforma un cambio brusco en uno suave:

var grande by remember { mutableStateOf(false) }
val tamano by animateDpAsState(if (grande) 160.dp else 80.dp, label = "tamano")
val color by animateColorAsState(if (grande) Color.Green else Color.Gray, label = "color")

Box(Modifier.size(tamano).background(color).clickable { grande = !grande })

Existen versiones para Float, Dp, Color, Int, Offset…

Animar el tamaño al cambiar el contenido

var expandida by remember { mutableStateOf(false) }
Card(Modifier.fillMaxWidth().animateContentSize().clickable { expandida = !expandida }) {
    Text(
        "Texto largo que se despliega al tocar la tarjeta…",
        Modifier.padding(16.dp), maxLines = if (expandida) Int.MAX_VALUE else 1
    )
}

Cambiar de contenido con transición

AnimatedContent(targetState = cuenta, label = "cuenta") { valor ->
    Text("$valor", fontSize = 48.sp)
}

Controlar la forma

Las animaciones aceptan una animationSpec:

Especificación Efecto
tween(500) Duración fija, 500 ms
spring() Rebote natural, como un muelle
repeatable(...) / infiniteRepeatable(...) Repetición
val x by animateFloatAsState(if (mover) 300f else 0f, animationSpec = spring(dampingRatio = Spring.DampingRatioMediumBouncy), label = "x")

Con medida

Una animación debe ayudar, no distraer. Mantén las transiciones cortas (150–400 ms) y evita animar muchas cosas a la vez.