Muchas de las API de Animation suelen aceptar parámetros para personalizar su comportamiento.
Cómo personalizar animaciones con el parámetro AnimationSpec
La mayoría de las API de Animation permiten a los desarrolladores personalizar las especificaciones de animaciones mediante un parámetro AnimationSpec
opcional.
val alpha: Float by animateFloatAsState( targetValue = if (enabled) 1f else 0.5f, // Configure the animation duration and easing. animationSpec = tween(durationMillis = 300, easing = FastOutSlowInEasing), label = "alpha" )
Hay diferentes tipos de AnimationSpec
para crear diferentes tipos de animaciones.
Crea animaciones basadas en la física con spring
spring
crea una animación basada en la física entre valores iniciales y finales. Toma 2 parámetros: dampingRatio
y stiffness
.
dampingRatio
define el nivel de efectividad que debería tener el resorte. El valor predeterminado es Spring.DampingRatioNoBouncy
.
Figura 1: Configura diferentes relaciones de amortiguamiento del resorte.
stiffness
define la velocidad con la que debe moverse el resorte hacia el valor final. El valor predeterminado es Spring.StiffnessMedium
.
Figura 2: Cómo establecer diferentes rigidez del resorte
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
spring
puede controlar las interrupciones de manera más fluida que los tipos AnimationSpec
basados en la duración, ya que garantiza la continuidad de la velocidad cuando cambia el valor objetivo entre las animaciones. spring
se usa como el valor predeterminado de AnimationSpec para muchas API de Animation, como animate*AsState
y updateTransition
.
Por ejemplo, si aplicamos una configuración spring
a la siguiente animación que se controla con el toque del usuario, cuando interrumpimos la animación a medida que avanza, puedes ver que usar tween
no responde tan bien como usar spring
.
Figura 3: Configurar las especificaciones de tween
en comparación con las de spring
para la animación y, luego, interrumpirla
Anima entre los valores inicial y final con una curva de aceleración con tween
tween
anima entre los valores inicial y final sobre el durationMillis
especificado mediante una curva de aceleración. tween
es la forma abreviada de la palabra between, ya que se encuentra entre dos valores.
También puedes especificar delayMillis
para posponer el inicio de la animación.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
Consulta Aceleración para obtener más información.
Anima a valores específicos en ciertos momentos con keyframes
keyframes
anima en función de los valores de instantánea especificados en diferentes marcas de tiempo en la duración de la animación. El valor de la animación se interpolará entre dos valores de fotogramas clave. Para cada uno de esos fotogramas clave, se puede especificar la aceleración a fin de determinar la curva de interpolación.
Es opcional especificar los valores en 0 ms y en el tiempo de duración. Si no especificas esos valores, se establecerán de manera predeterminada en los valores de inicio y finalización de la animación, respectivamente.
val value by animateFloatAsState( targetValue = 1f, animationSpec = keyframes { durationMillis = 375 0.0f at 0 using LinearOutSlowInEasing // for 0-15 ms 0.2f at 15 using FastOutLinearInEasing // for 15-75 ms 0.4f at 75 // ms 0.4f at 225 // ms }, label = "keyframe" )
Cómo repetir una animación con repeatable
repeatable
ejecuta una animación basada en la duración (como tween
o keyframes
) varias veces hasta que alcanza el recuento de iteración especificado. Puedes pasar el parámetro repeatMode
para especificar si la animación se debe repetir comenzando desde el principio (RepeatMode.Restart
) o desde el final (RepeatMode.Reverse
).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
Cómo repetir una animación de forma infinita con infiniteRepeatable
infiniteRepeatable
es como repeatable
, pero se repite durante una cantidad infinita de iteraciones.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
En las pruebas que usan ComposeTestRule
, no se ejecutan las animaciones que usan infiniteRepeatable
. El componente se renderizará con el valor inicial de cada valor animado.
Cómo ajustar de inmediato al valor final con snap
snap
es un AnimationSpec
especial que cambia inmediatamente el valor al valor final. Puedes especificar delayMillis
para retrasar el inicio de la animación.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
Cómo establecer una función de suavización personalizada
Las operaciones de AnimationSpec
basadas en la duración (como tween
o keyframes
) usan Easing
para ajustar la fracción de una animación. Eso permite que el valor de la animación se acelere y se ralentice, en lugar de moverse a una velocidad constante. La fracción es un valor entre 0 (inicio) y 1.0 (final) que indica el punto actual en la animación.
La aceleración es una función que toma un valor de fracción entre 0 y 1.0, y muestra un número de punto flotante. El valor que se muestra puede estar fuera de los límites para representar una suboscilación o una sobreoscilación. Se puede crear una aceleración personalizada como el siguiente código.
val CustomEasing = Easing { fraction -> fraction * fraction } @Composable fun EasingUsage() { val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, easing = CustomEasing ), label = "custom easing" ) // …… }
Compose proporciona varias funciones Easing
integradas que abarcan la mayoría de los casos de uso.
Consulta Velocidad: Material Design para obtener más información sobre qué tipo de aceleración debes usar según tu caso.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- Ver más
Anima los tipos de datos personalizados convirtiendo de AnimationVector
a AnimationVector
y viceversa
La mayoría de las APIs de animación de Compose admiten Float
, Color
, Dp
y otros tipos de datos básicos como valores de animación de forma predeterminada, pero a veces necesitas animar otros tipos de datos, como los que personalizas. Durante la animación, cualquier valor de animación se representa como un AnimationVector
. El valor se convierte en un AnimationVector
y viceversa por un TwoWayConverter
correspondiente para que el sistema de animación principal pueda controlarlos de manera uniforme. Por ejemplo, un Int
se representa como un AnimationVector1D
que tiene un solo valor de número de punto flotante.
TwoWayConverter
de Int
tiene este aspecto:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color
es, básicamente, un conjunto de 4 valores (rojo, verde, azul y alfa), por lo que Color
se convierte en un AnimationVector4D
que tiene 4 valores de número de punto flotante. De esta manera, cada tipo de datos que se usa en las animaciones se convierte en AnimationVector1D
, AnimationVector2D
, AnimationVector3D
o AnimationVector4D
, según su dimensionalidad. Esto permite que diferentes componentes del objeto se animen de forma independiente, cada uno con su propio seguimiento de velocidad. Se puede acceder a los convertidores integrados para tipos de datos básicos mediante convertidores como Color.VectorConverter
o Dp.VectorConverter
.
Si deseas agregar compatibilidad con un nuevo tipo de datos como un valor de animación, puedes crear tu propio TwoWayConverter
y proporcionarlo a la API. Por ejemplo, puedes usar animateValueAsState
para animar tu tipo de datos personalizados de la siguiente manera:
data class MySize(val width: Dp, val height: Dp) @Composable fun MyAnimation(targetSize: MySize) { val animSize: MySize by animateValueAsState( targetSize, TwoWayConverter( convertToVector = { size: MySize -> // Extract a float value from each of the `Dp` fields. AnimationVector2D(size.width.value, size.height.value) }, convertFromVector = { vector: AnimationVector2D -> MySize(vector.v1.dp, vector.v2.dp) } ), label = "size" ) }
La siguiente lista incluye algunos VectorConverter
integrados:
Color.VectorConverter
Dp.VectorConverter
Offset.VectorConverter
Int.VectorConverter
Float.VectorConverter
IntSize.VectorConverter
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Animaciones basadas en el valor
- Desarrollo de código iterativo {:#iterative-code-dev }
- Animaciones en Compose