Molte API di animazione accettano comunemente parametri per personalizzare il loro comportamento.
Personalizzare le animazioni con il parametro AnimationSpec
La maggior parte delle API di animazione consente agli sviluppatori di personalizzare le specifiche dell'animazione tramite un
parametro AnimationSpec facoltativo.
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" )
Esistono diversi tipi di AnimationSpec per creare diversi tipi di
animazione.
Creare animazioni basate sulla fisica con spring
spring crea un'animazione basata sulla fisica tra i valori iniziale e finale. Accetta
due parametri: dampingRatio e stiffness.
dampingRatio definisce l'elasticità della molla. Il valore predefinito è
Spring.DampingRatioNoBouncy.
stiffness definisce la velocità con cui la molla deve spostarsi verso il valore finale. Il valore predefinito è Spring.StiffnessMedium.
val value by animateFloatAsState( targetValue = 1f, animationSpec = spring( dampingRatio = Spring.DampingRatioHighBouncy, stiffness = Spring.StiffnessMedium ), label = "spring spec" )
spring può gestire le interruzioni in modo più fluido rispetto ai tipi AnimationSpec basati sulla durata perché garantisce la continuità della velocità quando il valore target cambia durante le animazioni. spring viene utilizzato come AnimationSpec predefinito da molte API di animazione, come animate*AsState e updateTransition.
Ad esempio, se applichiamo una configurazione spring alla seguente animazione
attivata dal tocco dell'utente, quando interrompi l'animazione mentre è in corso, puoi
notare che l'utilizzo di tween non risponde in modo fluido come l'utilizzo di spring.
tween rispetto a spring per l'animazione e interruzione.Anima tra i valori iniziale e finale con la curva di accelerazione con tween
tween anima i valori iniziale e finale nel periodo di tempo
durationMillis specificato utilizzando una curva di accelerazione. tween è l'abbreviazione della parola "tra".
Infatti, si trova tra due valori.
Puoi anche specificare delayMillis per posticipare l'inizio dell'animazione.
val value by animateFloatAsState( targetValue = 1f, animationSpec = tween( durationMillis = 300, delayMillis = 50, easing = LinearOutSlowInEasing ), label = "tween delay" )
Per saperne di più, consulta Accelerazione.
Animare valori specifici in determinati momenti con keyframes
keyframes viene animato in base ai valori dello snapshot specificati in diversi
timestamp durante la durata dell'animazione. In un determinato momento, il valore dell'animazione
verrà interpolato tra due valori dei fotogrammi chiave. Per ciascuno di questi
fotogrammi chiave, è possibile specificare l'accelerazione per determinare la curva di interpolazione.
È facoltativo specificare i valori a 0 ms e al momento della durata. Se non specifichi questi valori, vengono impostati come predefiniti i valori iniziale e finale dell'animazione, rispettivamente.
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" )
Animare in modo fluido tra i fotogrammi chiave con keyframesWithSplines
Per creare un'animazione che segue una curva uniforme durante la transizione tra i valori, puoi utilizzare keyframesWithSplines anziché le specifiche di animazione 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 } )
I fotogrammi chiave basati su spline sono particolarmente utili per il movimento 2D degli elementi sullo schermo.
I seguenti video mostrano le differenze tra keyframes e
keyframesWithSpline dato lo stesso insieme di coordinate x, y che un cerchio
deve seguire.
keyframes
|
keyframesWithSplines
|
|---|---|
Come puoi vedere, i fotogrammi chiave basati su spline offrono transizioni più fluide tra i punti, in quanto utilizzano curve di Bézier per animare in modo fluido gli elementi. Questa specifica è utile per un'animazione preimpostata. Tuttavia, se lavori con punti guidati dall'utente, è preferibile utilizzare le molle per ottenere una fluidità simile tra i punti, perché sono interrompibili.
Ripetere un'animazione con repeatable
repeatable esegue un'animazione basata sulla durata (ad esempio tween o keyframes)
ripetutamente fino a raggiungere il numero di iterazioni specificato. Puoi trasmettere il parametro
repeatMode per specificare se l'animazione deve ripetersi
iniziando dall'inizio (RepeatMode.Restart) o dalla fine
(RepeatMode.Reverse).
val value by animateFloatAsState( targetValue = 1f, animationSpec = repeatable( iterations = 3, animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "repeatable spec" )
Ripeti un'animazione all'infinito con infiniteRepeatable
infiniteRepeatable è simile a repeatable, ma si ripete per un numero infinito
di iterazioni.
val value by animateFloatAsState( targetValue = 1f, animationSpec = infiniteRepeatable( animation = tween(durationMillis = 300), repeatMode = RepeatMode.Reverse ), label = "infinite repeatable" )
Nei test che utilizzano
ComposeTestRule,
le animazioni che utilizzano infiniteRepeatable non vengono eseguite. Il componente verrà
visualizzato utilizzando il valore iniziale di ogni valore animato.
Passa immediatamente al valore finale con snap
snap è un AnimationSpec speciale che imposta immediatamente il valore sul
valore finale. Puoi specificare delayMillis per ritardare l'inizio dell'animazione.
val value by animateFloatAsState( targetValue = 1f, animationSpec = snap(delayMillis = 50), label = "snap spec" )
Impostare una funzione di accelerazione personalizzata
Le operazioni basate sulla durata AnimationSpec (come tween o keyframes) utilizzano
Easing per regolare la frazione di un'animazione. Ciò consente al valore di animazione di
accelerare e rallentare, anziché muoversi a una velocità costante. Frazione è un
valore compreso tra 0 (inizio) e 1,0 (fine) che indica il punto corrente dell'
animazione.
L'accelerazione è in realtà una funzione che accetta un valore frazionario compreso tra 0 e 1,0 e restituisce un float. Il valore restituito può essere al di fuori del limite per rappresentare un superamento o un mancato raggiungimento. È possibile creare un easing personalizzato come nel codice riportato di seguito.
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 fornisce diverse funzioni Easing integrate che coprono la maggior parte dei casi d'uso.
Per ulteriori informazioni su quale tipo di accelerazione utilizzare a seconda dello scenario, consulta Velocità - Material Design.
FastOutSlowInEasingLinearOutSlowInEasingFastOutLinearEasingLinearEasingCubicBezierEasing- Scopri di più
Animare i tipi di dati personalizzati convertendoli in e da AnimationVector
La maggior parte delle API di animazione Compose supporta Float, Color, Dp e altri tipi di dati di base come valori di animazione per impostazione predefinita, ma a volte è necessario animare altri tipi di dati, inclusi quelli personalizzati. Durante l'animazione, qualsiasi valore
di animazione è rappresentato come AnimationVector. Il valore viene convertito in un
AnimationVector e viceversa da un TwoWayConverter corrispondente, in modo che
il sistema di animazione principale possa gestirli in modo uniforme. Ad esempio, un Int è
rappresentato come un AnimationVector1D che contiene un singolo valore float.
TwoWayConverter per Int ha questo aspetto:
val IntToVector: TwoWayConverter<Int, AnimationVector1D> = TwoWayConverter({ AnimationVector1D(it.toFloat()) }, { it.value.toInt() })
Color è essenzialmente un insieme di 4 valori: rosso, verde, blu e alfa, quindi
Color viene convertito in un AnimationVector4D che contiene 4 valori float. In
questo modo, ogni tipo di dati utilizzato nelle animazioni viene convertito in
AnimationVector1D, AnimationVector2D, AnimationVector3D o
AnimationVector4D a seconda della sua dimensionalità. In questo modo, i diversi
componenti dell'oggetto possono essere animati in modo indipendente, ognuno con il proprio
monitoraggio della velocità. È possibile accedere ai convertitori integrati per i tipi di dati di base
utilizzando convertitori come Color.VectorConverter o Dp.VectorConverter.
Quando vuoi aggiungere il supporto per un nuovo tipo di dati come valore di animazione, puoi creare il tuo TwoWayConverter e fornirlo all'API. Ad esempio, puoi
utilizzare animateValueAsState per animare il tuo tipo di dati personalizzato nel seguente modo:
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" ) }
L'elenco seguente include alcuni VectorConverter integrati:
Color.VectorConverterDp.VectorConverterOffset.VectorConverterInt.VectorConverterFloat.VectorConverterIntSize.VectorConverter
Consigliati per te
- Nota: il testo del link viene visualizzato quando JavaScript è disattivato
- Animazioni basate sul valore
- Sviluppo iterativo del codice {:#iterative-code-dev }
- Animazioni in Compose