Il movimento basato sulla fisica è determinato dalla forza. La forza della molla è una delle forze che guida l'interattività e il movimento. Una forza della molla ha le seguenti proprietà: smorzamento e rigidità. In un'animazione a molla, il valore e la velocità vengono calcolati in base alla forza della molla applicata a ciascun fotogramma.
Se vuoi che le animazioni dell'app rallentino solo in una direzione, valuta la possibilità di utilizzare un'animazione flessione basata sull'attrito.
Ciclo di vita di un'animazione primaverile
In un'animazione a molla, la classe SpringForce
consente di personalizzare la rigidità della molla, il rapporto di smorzamento e la
posizione finale. Non appena inizia l'animazione, la forza della molla aggiorna
il valore dell'animazione e la velocità su ciascun frame. L'animazione continua finché la forza della molla non raggiunge un equilibrio.
Ad esempio, se trascini l'icona di un'app sullo schermo e poi la rilasci sollevando il dito dall'icona, l'icona torna nella posizione originale di una forza invisibile ma nota.
La Figura 1 mostra un effetto elastico simile. Il segno più (+) al centro del cerchio indica la forza applicata tramite un gesto di tocco.
Creare un'animazione primaverile
I passaggi generali per creare un'animazione molla per la tua applicazione sono i seguenti:
- Aggiungi la libreria di supporto Per utilizzare le classi di animazione primaverile, devi aggiungere la libreria di supporto al tuo progetto.
- Creare un'animazione primaverile:
Il passaggio principale consiste nel creare un'istanza di
classe
SpringAnimation
e impostare i parametri del comportamento del movimento. - (Facoltativo) Registra i listener:
registra i listener per osservare le modifiche al ciclo di vita dell'animazione e gli aggiornamenti dei valori
dell'animazione.
Nota: il listener di aggiornamenti deve essere registrato solo se devi eseguire un aggiornamento per frame alle modifiche dei valori dell'animazione. Un listener di aggiornamenti impedisce la potenziale esecuzione dell'animazione in un thread separato.
- (Facoltativo) Rimuovi i listener: rimuovi i listener che non sono più in uso.
- (Facoltativo) Imposta un valore iniziale: personalizza il valore iniziale dell'animazione.
- (Facoltativo) Imposta un intervallo di valori: imposta l'intervallo di valori dell'animazione per limitare i valori all'interno dell'intervallo minimo e massimo.
- (Facoltativo) Imposta la velocità di inizio: Imposta la velocità di inizio per l'animazione.
- (Facoltativo) Imposta le proprietà della molla: Imposta il rapporto di smorzamento e la rigidità della molla.
- (Facoltativo) Crea una molla personalizzata: crea una molla personalizzata nel caso in cui non intendi utilizzare la molla predefinita o voglia usarne una comune in tutta l'animazione.
- Avvia animazione: Avvia l'animazione primaverile.
- (Facoltativo) Annulla animazione: annulla l'animazione nel caso in cui l'utente esce improvvisamente dall'app o la visualizzazione non sia più visibile.
Le seguenti sezioni descrivono in dettaglio i passaggi generali per la creazione di un'animazione primavera.
Aggiungi la libreria di supporto
Per utilizzare la libreria di supporto basata sulla fisica, devi aggiungere la libreria di supporto al tuo progetto come segue:
- Apri il file
build.gradle
per il modulo dell'app. Aggiungi la libreria di supporto alla sezione
dependencies
.trendy
dependencies { def dynamicanimation_version = '1.0.0' implementation "androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version" }
Kotlin
dependencies { val dynamicanimation_version = "1.0.0" implementation("androidx.dynamicanimation:dynamicanimation:$dynamicanimation_version") }
Per visualizzare le versioni correnti di questa libreria, vedi le informazioni su Dynamicanimation nella pagina versions.
Creare un'animazione primaverile
La classe SpringAnimation
consente di creare
un'animazione primaverile per un oggetto. Per realizzare un'animazione primaverile, devi
creare un'istanza della classe SpringAnimation
e fornire un oggetto, la proprietà di un oggetto che vuoi animare e una
posizione finale facoltativa della molla in cui vuoi che si fermi.
Nota: al momento della creazione di un'animazione primaverile, la posizione finale della molla è facoltativa. Tuttavia, deve essere definito prima di avviare l'animazione.
Kotlin
val springAnim = findViewById<View>(R.id.imageView).let { img -> // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0f) }
Java
final View img = findViewById(R.id.imageView); // Setting up a spring animation to animate the view’s translationY property with the final // spring position at 0. final SpringAnimation springAnim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y, 0);
L'animazione a molla può animare le visualizzazioni sullo schermo modificando le proprietà effettive degli oggetti vista. Nel sistema sono disponibili le seguenti visualizzazioni:
ALPHA
: rappresenta la trasparenza alpha della vista. Per impostazione predefinita, il valore è 1 (opaco) e il valore 0 rappresenta la massima trasparenza (non visibile).TRANSLATION_X
,TRANSLATION_Y
eTRANSLATION_Z
: queste proprietà controllano la posizione della vista come delta rispetto alla coordinata sinistra, alla coordinata superiore e all'elevazione, che sono impostate dal relativo contenitore di layout.TRANSLATION_X
descrive la coordinata a sinistra.TRANSLATION_Y
descrive la coordinata superiore.TRANSLATION_Z
descrive la profondità della vista rispetto alla sua elevazione.
ROTATION
,ROTATION_X
eROTATION_Y
: queste proprietà controllano la rotazione in 2D (proprietàrotation
) e in 3D intorno al punto pivot.SCROLL_X
eSCROLL_Y
: queste proprietà indicano l'offset di scorrimento dell'origine sinistra e il bordo superiore in pixel. Indica anche la posizione in termini di quanto è stata fatta scorrere la pagina.SCALE_X
eSCALE_Y
: queste proprietà controllano la scalabilità 2D di una vista intorno al relativo punto pivot.X
,Y
eZ
: queste sono proprietà di utilità di base che descrivono la posizione finale della vista nel relativo container.X
è una somma del valore a sinistra e diTRANSLATION_X
.Y
è una somma del valore superiore e diTRANSLATION_Y
.Z
è una somma del valore di elevazione e diTRANSLATION_Z
.
Registra listener
La classe DynamicAnimation
offre due
listener: OnAnimationUpdateListener
e OnAnimationEndListener
.
Questi listener ascoltano gli aggiornamenti dell'animazione, ad esempio quando si verifica una modifica nel valore dell'animazione e quando l'animazione termina.
OnAnimationUpdateListener
Se vuoi animare più viste per creare un'animazione concatenata, puoi
impostare OnAnimationUpdateListener
in modo che riceva un callback ogni volta che viene apportata una modifica alla proprietà
della vista corrente. Il callback avvisa l'altra vista di aggiornare la sua posizione primaverile in base alla modifica effettuata nella proprietà della vista corrente. Per registrare il listener, segui questi passaggi:
-
Chiama il metodo
addUpdateListener()
e collega il listener all'animazione.Nota: devi registrare il listener di aggiornamenti prima dell'inizio dell'animazione. Tuttavia, il listener di aggiornamenti deve essere registrato solo se devi eseguire un aggiornamento per frame alle modifiche dei valori dell'animazione. Un listener di aggiornamenti impedisce la potenziale esecuzione dell'animazione in un thread separato.
-
Esegui l'override del metodo
onAnimationUpdate()
per notificare al chiamante la modifica dell'oggetto attuale. Il seguente codice campione illustra l'utilizzo complessivo diOnAnimationUpdateListener
.
Kotlin
// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties val (anim1X, anim1Y) = findViewById<View>(R.id.view1).let { view1 -> SpringAnimation(view1, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y) } val (anim2X, anim2Y) = findViewById<View>(R.id.view2).let { view2 -> SpringAnimation(view2, DynamicAnimation.TRANSLATION_X) to SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y) } // Registering the update listener anim1X.addUpdateListener { _, value, _ -> // Overriding the method to notify view2 about the change in the view1’s property. anim2X.animateToFinalPosition(value) } anim1Y.addUpdateListener { _, value, _ -> anim2Y.animateToFinalPosition(value) }
Java
// Creating two views to demonstrate the registration of the update listener. final View view1 = findViewById(R.id.view1); final View view2 = findViewById(R.id.view2); // Setting up a spring animation to animate the view1 and view2 translationX and translationY properties final SpringAnimation anim1X = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim1Y = new SpringAnimation(view1, DynamicAnimation.TRANSLATION_Y); final SpringAnimation anim2X = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_X); final SpringAnimation anim2Y = new SpringAnimation(view2, DynamicAnimation.TRANSLATION_Y); // Registering the update listener anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { // Overriding the method to notify view2 about the change in the view1’s property. @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2X.animateToFinalPosition(value); } }); anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() { @Override public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value, float velocity) { anim2Y.animateToFinalPosition(value); } });
OnAnimationEndListener
OnAnimationEndListener
avvisa la fine di un'animazione. Puoi configurare il listener in modo che riceva il callback ogni volta che l'animazione raggiunge l'equilibrio o viene annullata. Per registrare il listener, segui questi passaggi:
-
Chiama il metodo
addEndListener()
e collega il listener all'animazione. -
Esegui l'override del metodo
onAnimationEnd()
per ricevere una notifica ogni volta che un'animazione raggiunge l'equilibrio o viene annullata.
Rimuovi listener
Per interrompere la ricezione dei callback di aggiornamento dell'animazione e del callback di fine animazione, chiama rispettivamente i metodi removeUpdateListener()
e removeEndListener()
.
Imposta valore iniziale animazione
Per impostare il valore iniziale dell'animazione, chiama il metodo
setStartValue()
e trasmetti il valore iniziale dell'animazione. Se non imposti il valore iniziale, l'animazione utilizza il valore corrente della proprietà dell'oggetto come valore iniziale.
Imposta intervallo di valori dell'animazione
Puoi impostare i valori minimi e massimi dell'animazione quando vuoi limitare il valore della proprietà a un determinato intervallo. Inoltre, è utile controllare l'intervallo nel caso in cui tu abbia animato proprietà che hanno un intervallo intrinseco, come alfa (da 0 a 1).
-
Per impostare il valore minimo, chiama il metodo
setMinValue()
e trasmetti il valore minimo della proprietà. -
Per impostare il valore massimo, chiama il metodo
setMaxValue()
e trasmetti il valore massimo della proprietà.
Entrambi i metodi restituiscono l'animazione per la quale viene impostato il valore.
Nota: se hai impostato il valore iniziale e hai definito un intervallo di valori dell'animazione, assicurati che il valore iniziale rientri nell'intervallo di valori minimo e massimo.
Imposta velocità iniziale
La velocità di avvio definisce la velocità con cui cambia la proprietà dell'animazione all'inizio dell'animazione. La velocità iniziale predefinita è impostata su zero pixel al secondo. Puoi impostare la velocità con la velocità dei gesti tattili o utilizzando un valore fisso come velocità iniziale. Se scegli di fornire un valore fisso, ti consigliamo di definire il valore in dp al secondo e di convertirlo in pixel al secondo. La definizione del valore in dp al secondo consente alla velocità di essere indipendente dalla densità e dai fattori di forma. Per saperne di più sulla conversione del valore in pixel al secondo, consulta la sezione Conversione dei dp al secondo in pixel al secondo.
Per impostare la velocità, chiama il metodo setStartVelocity()
e trasmettila in pixel al secondo. Il metodo restituisce l'oggetto di forza della molla su cui è impostata la velocità.
Nota: utilizza i metodi di classe GestureDetector.OnGestureListener
o VelocityTracker
per recuperare e calcolare la velocità dei gesti tattili.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000) val velocity = vt.yVelocity setStartVelocity(velocity) } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Compute velocity in the unit pixel/second vt.computeCurrentVelocity(1000); float velocity = vt.getYVelocity(); anim.setStartVelocity(velocity);
Conversione dei dp al secondo in pixel al secondo
La velocità di una molla deve essere in pixel al secondo. Se scegli di fornire un valore fisso come inizio della velocità, indica il valore in dp al secondo, quindi convertilo in pixel al secondo. Per la conversione, utilizza il metodo
applyDimension()
della classe TypedValue
. Fai riferimento al
seguente codice campione:
Kotlin
val pixelPerSecond: Float = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, resources.displayMetrics)
Java
float pixelPerSecond = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpPerSecond, getResources().getDisplayMetrics());
Impostare le proprietà della molla
La classe SpringForce
definisce il getter e i metodi del setter per ciascuna delle proprietà della molla, come il rapporto di smorzamento e la rigidità. Per impostare le proprietà della molla, è importante recuperare l'oggetto forza della molla o creare una forza della molla personalizzata sulla quale poter impostare le proprietà. Per ulteriori informazioni sulla creazione di una forza della molla personalizzata, consulta la sezione Creare una forza della molla personalizzata.
Suggerimento: quando utilizzi i metodi del setter, puoi creare una catena di metodi poiché tutti i metodi del setter restituiscono l'oggetto spring force.
Rapporto di attenuazione
Il rapporto di smorzamento descrive una graduale riduzione dell'oscillazione della molla. L'utilizzo del rapporto di smorzamento ti consente di definire la velocità di decadimento delle oscillazioni da un rimbalzo all'altro. Esistono quattro modi diversi per umidificare una molla:
- Il sovrasmorzamento si verifica quando il rapporto di smorzamento è maggiore di uno. Consente all'oggetto di tornare delicatamente nella posizione di riposo.
- Lo smorzamento critico si verifica quando il rapporto di smorzamento è uguale a uno. Consente all'oggetto di tornare alla posizione di riposo nell'arco di tempo più breve.
- Il sottosmorzamento si verifica quando il rapporto di smorzamento è inferiore a uno. Consente di superare l'oggetto in eccesso superando la posizione di riposo, per poi raggiungere gradualmente la posizione di riposo.
- Lo smorzamento si verifica quando il rapporto di smorzamento è pari a zero. Consente all'oggetto di oscillare all'infinito.
Per aggiungere il rapporto di smorzamento alla molla, segui questi passaggi:
-
Richiama il metodo
getSpring()
per recuperare la molla e aggiungere il rapporto di smorzamento. -
Richiama il metodo
setDampingRatio()
e trasmetti il rapporto di smorzamento che vuoi aggiungere alla molla. Il metodo restituisce l'oggetto di forza della molla su cui è impostato il rapporto di smorzamento.Nota: il rapporto di smorzamento deve essere un numero non negativo. Se imposti il rapporto di smorzamento su zero, la molla non raggiungerà mai la posizione di riposo. In altre parole, oscilla all'infinito.
Nel sistema sono disponibili le seguenti costanti del rapporto di smorzamento:
DAMPING_RATIO_HIGH_BOUNCY
DAMPING_RATIO_MEDIUM_BOUNCY
DAMPING_RATIO_LOW_BOUNCY
DAMPING_RATIO_NO_BOUNCY
Figura 2: rimbalzo elevato
Figura 3: rimbalzo medio
Figura 4: rimbalzo basso
Figura 5: nessun rimbalzo
Il rapporto di smorzamento predefinito è impostato su DAMPING_RATIO_MEDIUM_BOUNCY
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the damping ratio to create a low bouncing effect. spring.dampingRatio = SpringForce.DAMPING_RATIO_LOW_BOUNCY … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the damping ratio to create a low bouncing effect. anim.getSpring().setDampingRatio(SpringForce.DAMPING_RATIO_LOW_BOUNCY); …
Rigidità
La rigidezza definisce la costante della molla, che misura la forza della molla. Una molla rigida applica più forza all'oggetto attaccato quando la molla non è in posizione di riposo. Per aumentare la rigidità della molla, segui questi passaggi:
-
Richiama il metodo
getSpring()
per recuperare la molla e aggiungere la rigidità. -
Richiama il metodo
setStiffness()
e trasmetti il valore di rigidità che vuoi aggiungere alla molla. Il metodo restituisce l'oggetto della forza della molla su cui è impostata la rigidezza.Nota: la rigidità deve essere un numero positivo.
Nel sistema sono disponibili le seguenti costanti di rigidità:
Figura 6: rigidità elevata
Figura 7: rigidità media
Figura 8: bassa rigidità
Figura 9: rigidità molto bassa
La rigidità predefinita è impostata su STIFFNESS_MEDIUM
.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Setting the spring with a low stiffness. spring.stiffness = SpringForce.STIFFNESS_LOW … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Setting the spring with a low stiffness. anim.getSpring().setStiffness(SpringForce.STIFFNESS_LOW); …
Creare una forza della molla personalizzata
Puoi creare una forza della molla personalizzata in alternativa all'utilizzo della forza della molla predefinita. La forza della molla personalizzata consente di condividere la stessa istanza della forza della molla tra più animazioni della molla. Dopo aver creato la forza della molla, puoi impostare proprietà come il rapporto di smorzamento e la rigidità.
-
Crea un oggetto
SpringForce
.SpringForce force = new SpringForce();
-
Assegna le proprietà richiamando i rispettivi metodi. Puoi anche creare una catena di metodi.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);
-
Richiama il metodo
setSpring()
per impostare la molla per l'animazione.setSpring(force);
Avvia animazione
Esistono due modi per avviare un'animazione primaverile: richiamando
start()
o il metodo
animateToFinalPosition()
. Entrambi i metodi devono essere chiamati sul thread principale.
animateToFinalPosition()
esegue due attività:
- Imposta la posizione finale della molla.
- Avvia l'animazione, se non è stata avviata.
Poiché il metodo aggiorna la posizione finale della molla e, se necessario, avvia l'animazione, puoi richiamare questo metodo in qualsiasi momento per modificare il corso di un'animazione. Ad esempio, in un'animazione molla concatenata, l'animazione di una vista dipende da un'altra. Per un'animazione di questo tipo, è più pratico utilizzare il metodo animateToFinalPosition()
. Se utilizzi questo metodo in un'animazione a molla concatenata, non dovrai preoccuparti se l'animazione successiva da aggiornare è attualmente in esecuzione.
La Figura 10 illustra un'animazione a molla concatenata, in cui l'animazione di una vista dipende da un'altra.
Per utilizzare il metodo animateToFinalPosition()
, chiama il metodo animateToFinalPosition()
e passa la posizione di riposo della molla. Puoi anche impostare la posizione di riposo della molla chiamando il metodo setFinalPosition()
.
Il metodo start()
non imposta immediatamente il valore della proprietà sul valore iniziale. Il valore della proprietà cambia a ogni impulso di animazione, che si verifica prima del passaggio di disegno.
Di conseguenza, le modifiche si riflettono nel frame successivo, come se i valori fossero impostati immediatamente.
Kotlin
findViewById<View>(R.id.imageView).also { img -> SpringAnimation(img, DynamicAnimation.TRANSLATION_Y).apply { … // Starting the animation start() … } }
Java
final View img = findViewById(R.id.imageView); final SpringAnimation anim = new SpringAnimation(img, DynamicAnimation.TRANSLATION_Y); … // Starting the animation anim.start(); …
Annulla animazione
Puoi annullare l'animazione o saltarla alla fine. La situazione ideale in cui devi annullare o passare alla fine dell'animazione è quando un'interazione utente richiede l'interruzione immediata dell'animazione. Questo accade principalmente quando un utente esce improvvisamente da un'app o la visualizzazione diventa invisibile.
Puoi utilizzare due metodi per terminare l'animazione.
Il metodo cancel()
termina l'animazione in base al valore in cui si trova. Il metodo skipToEnd()
salta l'animazione al valore finale e poi la termina.
Prima di poter terminare l'animazione, è importante controllare
lo stato della molla. Se lo stato non è smorzato, l'animazione non può mai raggiungere la posizione di riposo.
Per controllare lo stato della molla, chiama il metodo canSkipToEnd()
. Se
la molla è smorzata, il metodo restituisce true
, altrimenti
false
.
Quando conosci lo stato della molla, puoi terminare un'animazione utilizzando i metodi skipToEnd()
o cancel()
. Il metodo cancel()
deve essere chiamato solo sul thread principale.
Nota: in generale, il metodo skipToEnd()
determina un salto visivo.