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. Richiede
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 predefinita da molte API di animazione, come animate*AsState
e updateTransition
.
Ad esempio, se applichiamo una configurazione spring
alla seguente animazione
basata sul tocco dell'utente, quando interrompiamo l'animazione in corso, puoi
notare che l'utilizzo di tween
non risponde in modo fluido come l'utilizzo di spring
.
tween
e 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",
in quanto 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 e 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.
FastOutSlowInEasing
LinearOutSlowInEasing
FastOutLinearEasing
LinearEasing
CubicBezierEasing
- 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
tracciamento 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" ) }
Il seguente elenco include alcuni VectorConverter
incorporati:
Color.VectorConverter
Dp.VectorConverter
Offset.VectorConverter
Int.VectorConverter
Float.VectorConverter
IntSize.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