Geralmente, muitas das APIs de animação aceitam parâmetros para personalização de comportamentos.
Personalizar animações com o parâmetro AnimationSpec
A maioria das APIs de animação permite que os desenvolvedores personalizem as especificações de animação usando um 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" )
Existem diferentes tipos de AnimationSpec para criação de diferentes tipos de animação.
Criar animação baseada em física com spring
A spring cria uma animação baseada em física entre os valores inicial e final. Ela
precisa de dois parâmetros: dampingRatio e stiffness.
dampingRatio define o grau de mobilidade da spring. O valor padrão é Spring.DampingRatioNoBouncy.
stiffness define a velocidade de movimento da spring em direção ao valor final. O valor padrão é Spring.StiffnessMedium.
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
A spring pode processar interrupções de forma melhor que tipos de AnimationSpec baseados em duração, porque garante a continuidade da velocidade quando o valor de destino muda entre animações. A spring é usada como o AnimationSpec padrão por muitas APIs de animação, como animate*AsState e updateTransition.
Por exemplo, se aplicarmos uma configuração de spring à animação a seguir, que é orientada pelo toque do usuário, ao interromper a animação à medida que ela progride, você poderá notar que o uso de tween não responde tão bem quanto o uso de spring.
tween versus spring para animação e interrompê-la.Animar entre valores inicial e final com curva de easing com tween
A tween executa animações entre os valores inicial e final na durationMillis especificada, usando uma curva de easing. tween é uma abreviação da palavra "between" (entre, em inglês), já que ela fica entre dois valores.
Também é possível especificar delayMillis para adiar o início da animação.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
Consulte Easing para ver mais informações.
Animar para valores específicos em determinados momentos com keyframes
As keyframes executam animações com base nos valores resumidos especificados em carimbos de data/hora diferentes na duração da animação. O valor de animação
será interpolado entre dois valores keyframe a qualquer momento. O easing pode ser especificado
para qualquer um dos keyframes para determinar a curva de interpolação.
Especificar os valores como 0 ms e o tempo de duração é opcional. Caso esses valores não sejam especificados, o padrão será os valores inicial e final da animação, 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" )
Animar entre frames-chave sem problemas com keyframesWithSplines
Para criar uma animação que siga uma curva suave à medida que faz a transição entre
valores, use keyframesWithSplines em vez de especificações de animação
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 } )
Os frames-chave baseados em spline são particularmente úteis para o movimento 2D de itens na tela.
Os vídeos a seguir mostram as diferenças entre keyframes e
keyframesWithSpline considerando o mesmo conjunto de coordenadas x e y que um círculo
precisa seguir.
keyframes
|
keyframesWithSplines
|
|---|---|
Como você pode ver, os frames-chave baseados em spline oferecem transições mais suaves entre os pontos, já que usam curvas de Bézier para animar itens sem problemas. Essa especificação é útil para uma animação predefinida. No entanto, se você estiver trabalhando com pontos orientados pelo usuário, é preferível usar springs para alcançar uma suavidade semelhante entre os pontos, porque eles são interrompíveis.
Repetir uma animação com repeatable
A repeatable executa uma animação baseada em duração (como tween ou keyframes) repetidamente, até alcançar a contagem de iteração especificada. É possível transmitir o parâmetro repeatMode para especificar se a animação vai ser repetida começando do início (RepeatMode.Restart) ou do final (RepeatMode.Reverse).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
Repetir uma animação infinitamente com infiniteRepeatable
A infiniteRepeatable é semelhante a repeatable, mas essa função se repete por uma quantidade infinita de iterações.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
Animações que usam infiniteRepeatable
não são executadas em testes que usam
ComposeTestRule. O componente será renderizado usando o valor inicial de cada valor de animação.
Alinhar imediatamente ao valor final com snap
A snap é uma AnimationSpec especial que muda imediatamente o valor para o valor final. Você pode especificar delayMillis para atrasar o início da animação.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
Definir uma função de easing personalizada
As operações AnimationSpec baseadas em duração (como tween ou keyframes) usam Easing para ajustar a fração da animação. Isso permite que o valor de animação
acelere e desacelere, em vez de se mover a uma taxa constante. Uma fração é um
valor entre 0 (início) e 1,0 (fim) indicando o ponto atual da
animação.
O easing é, na verdade, uma função que usa um valor de fração entre 0 e 1,0 e retorna um ponto flutuante. O valor retornado pode estar fora do limite para representar uma ultrapassagem ou uma redução. Um easing personalizado pode ser criado, como no código abaixo.
val CustomEasing = Easing { fraction -> fraction * fraction } @Composable fun EasingUsage() { val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, easing = CustomEasing ), label = "custom easing" ) // …… }
O Compose oferece várias funções Easing integradas que abrangem a maioria dos casos de uso.
Consulte Speed - Material Design (link em inglês) para ver mais
informações sobre qual easing usar dependendo da situação.
FastOutSlowInEasingLinearOutSlowInEasingFastOutLinearEasingLinearEasingCubicBezierEasing- Ver mais
Animar tipos de dados personalizados convertendo de e para AnimationVector
A maioria das APIs de animação do Compose oferece suporte a Float, Color, Dp e outros tipos de dados básicos como valores de animação por padrão. Contudo, às vezes é necessário animar outros tipos de dados, incluindo dados personalizados. Durante a animação, qualquer valor de animação é representado como um AnimationVector. O valor é convertido em um
AnimationVector, e vice-versa, por um TwoWayConverter correspondente para que
o sistema de animação principal possa processá-lo de maneira uniforme. Por exemplo, uma Int é
representada como um AnimationVector1D contendo um único valor flutuante.
Para TwoWayConverter, o Int é assim:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
A Color é essencialmente um conjunto de quatro valores: vermelho, verde, azul e alfa. A
Color é convertida em um AnimationVector4D contendo quatro valores flutuantes. Dessa
forma, cada tipo de dados usado nas animações é convertido em
AnimationVector1D, AnimationVector2D, AnimationVector3D ou
AnimationVector4D, dependendo da dimensionalidade. Isso permite que diferentes componentes do objeto sejam animados de forma independente, com rastreamentos de velocidade próprios. Os conversores integrados para tipos de dados básicos podem ser acessados usando conversores como Color.VectorConverter ou Dp.VectorConverter.
Caso queira adicionar compatibilidade com um novo tipo de dados como um valor de animação, crie seu próprio TwoWayConverter e forneça-o à API. Por exemplo, é possível usar animateValueAsState para animar o tipo de dados personalizado da seguinte forma:
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" ) }
A lista a seguir inclui alguns VectorConverters integrados:
Color.VectorConverterDp.VectorConverterOffset.VectorConverterInt.VectorConverterFloat.VectorConverterIntSize.VectorConverter
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado.
- Animações com base no valor
- Desenvolvimento de código iterativo {:#iterative-code-dev }
- Animações no Compose