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
.
stiffness
define la velocidad con la que debe moverse el resorte hacia el valor final. El valor predeterminado es Spring.StiffnessMedium
.
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 de spring
a la siguiente animación controlada por el toque del usuario, cuando interrumpimos la animación a medida que avanza, se puede ver que usar tween
no responde con la misma fluidez que usar spring
.
tween
en comparación con las de spring
para la animación y cómo interrumpirlaAnima entre los valores inicial y final con la 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 abreviatura de la palabra entre, 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 momentos determinados 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 animar entre fotogramas clave de forma fluida con keyframesWithSplines
Para crear una animación que siga una curva suave a medida que realiza la transición entre valores, puedes usar keyframesWithSplines
en lugar de las especificaciones de animación keyframes
.
val offset by animateOffsetAsState( targetValue = Offset(300f, 300f), animationSpec = keyframesWithSpline { durationMillis = 6000 Offset(0f, 0f) at 0 Offset(150f, 200f) atFraction 0.5f Offset(0f, 100f) atFraction 0.7f } )
Los fotogramas clave basados en splines son especialmente útiles para el movimiento en 2D de elementos en la pantalla.
En los siguientes videos, se muestran las diferencias entre keyframes
y keyframesWithSpline
con el mismo conjunto de coordenadas X e Y que debería seguir un círculo.
keyframes
|
keyframesWithSplines
|
---|---|
Como puedes ver, los fotogramas clave basados en splines ofrecen transiciones más fluidas entre los puntos, ya que usan curvas de Bézier para animar los elementos de forma fluida. Esta especificación es útil para una animación predeterminada. Sin embargo, si trabajas con puntos controlados por el usuario, es preferible usar resortes para lograr una suavidad similar entre los puntos, ya que son interrumpibles.
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.
Ajuste 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 aceleració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 tipos de datos personalizados convirtiéndolos a AnimationVector
y desde AnimationVector
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, incluidos los personalizados. 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 con 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" ) }
En la siguiente lista, se incluyen 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