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ções baseadas 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. 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 à seguinte animação, que é
acionada pelo toque do usuário, ao interromper a animação enquanto ela está em andamento, você
vai perceber que o uso de tween não responde tão bem quanto o uso de spring.
tween em vez de especificações spring para animação e interrompê-la.Animar entre valores inicial e final com curva de easing usando tween
tween executa animações entre os valores inicial e final na
durationMillis especificada, usando uma curva de easing. tween é uma abreviação da palavra "entre", já que 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 mais informações.
Animar para valores específicos em determinados momentos com keyframes
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 de maneira suave com keyframesWithSplines
Para criar uma animação que segue uma curva suave ao fazer 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 keyframes 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 com o mesmo conjunto de coordenadas x e y que um círculo deve seguir.
keyframes
|
keyframesWithSplines
|
|---|---|
Como você pode ver, os frames-chave baseados em spline oferecem transições mais suaves entre pontos, já que usam curvas de Bézier para animar itens de forma suave. Essa especificação é útil para uma animação predefinida. No entanto, se você estiver trabalhando com pontos definidos pelo usuário, é preferível usar molas para alcançar uma suavidade semelhante entre os pontos, porque elas podem ser interrompidas.
Repetir uma animação com o repeatable
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
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.
Ajustar imediatamente para o valor final com snap
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 aceleração 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 Velocidade - Material Design (link em inglês) para mais informações sobre qual easing usar dependendo da situação.
FastOutSlowInEasingLinearOutSlowInEasingFastOutLinearEasingLinearEasingCubicBezierEasing- Mostrar mais
Animar tipos de dados personalizados convertendo para e de 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