Il movimento basato sulla fisica è determinato dalla forza. La forza elastica è una di queste forze che guidano l'interattività e il movimento. Una forza elastica ha le seguenti proprietà: smorzamento e rigidità. In un'animazione basata su una molla, il valore e la velocità vengono calcolati in base alla forza della molla applicata a ogni frame.
Se vuoi che le animazioni della tua app rallentino in una sola direzione, valuta la possibilità di utilizzare un'animazione di scorrimento veloce basata sull'attrito.
Ciclo di vita di un'animazione con effetto molla
In un'animazione basata su una molla, la classe SpringForce
ti consente di personalizzare la rigidità della molla, il suo rapporto di smorzamento e la sua
posizione finale. Non appena inizia l'animazione, la forza della molla aggiorna
il valore dell'animazione e la velocità su ogni fotogramma. L'animazione continua
finché la forza della molla non raggiunge un equilibrio.
Ad esempio, se trascini l'icona di un'app sullo schermo e la rilasci sollevando il dito dall'icona, l'icona torna alla sua posizione originale grazie a una forza invisibile ma familiare.
La figura 1 mostra un effetto molla simile. Il segno più (+) al centro del cerchio indica la forza applicata tramite un gesto tocco.
Creare un'animazione con effetto molla
I passaggi generali per creare un'animazione con effetto molla per la tua applicazione sono i seguenti:
- Aggiungi la libreria di supporto Devi aggiungere la libreria di supporto al tuo progetto per utilizzare le classi di animazione con effetto molla.
- Crea un'animazione con effetto molla:
Il primo passaggio consiste nel creare un'istanza della
classe
SpringAnimatione impostare i parametri di comportamento del movimento. - (Facoltativo) Registra listener:
Registra i listener per monitorare le modifiche del ciclo di vita dell'animazione e gli aggiornamenti dei valori dell'animazione.
Nota:il listener di aggiornamento deve essere registrato solo se hai bisogno di un aggiornamento per frame delle modifiche al valore dell'animazione. Un listener di aggiornamento impedisce che l'animazione venga eseguita su un thread separato.
- (Facoltativo) Rimuovi i listener: Rimuovi i listener che non vengono più utilizzati.
- (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à iniziale: Imposta la velocità iniziale dell'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 se non intendi utilizzare quella predefinita o se vuoi utilizzarne una comune per tutta l'animazione.
- Avvia animazione Avvia l'animazione con effetto molla.
- (Facoltativo) Annulla animazione: Annulla l'animazione nel caso in cui l'utente esca bruscamente dall'app o la visualizzazione diventi invisibile.
Le sezioni seguenti descrivono in dettaglio i passaggi generali per creare un'animazione a molla.
Aggiungere la libreria di supporto
Per utilizzare la libreria di supporto basata sulla fisica, devi aggiungerla al tuo progetto come segue:
- Apri il file
build.gradleper il modulo dell'app. Aggiungi la libreria di supporto alla sezione
dependencies.Alla moda
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 attuali di questa libreria, consulta le informazioni su Dynamicanimation nella pagina Versioni.
Creare un'animazione con effetto molla
La classe SpringAnimation ti consente di creare
un'animazione con effetto molla per un oggetto. Per creare un'animazione con effetto molla, devi
creare un'istanza della classe SpringAnimation
e fornire un oggetto, la proprietà di un oggetto da animare e una
posizione finale della molla facoltativa in cui vuoi che l'animazione si fermi.
Nota: al momento della creazione di un'animazione con effetto molla, 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 basata sulla molla può animare le visualizzazioni sullo schermo modificando le proprietà effettive negli oggetti di visualizzazione. Nel sistema sono disponibili le seguenti visualizzazioni:
ALPHA: Rappresenta la trasparenza alfa nella visualizzazione. Il valore predefinito è 1 (opaco), mentre un valore pari a 0 rappresenta la trasparenza completa (non visibile).TRANSLATION_X,TRANSLATION_YeTRANSLATION_Z: queste proprietà controllano la posizione della visualizzazione come delta rispetto alla coordinata sinistra, alla coordinata superiore e all'elevazione, che vengono impostate dal relativo contenitore di layout.TRANSLATION_Xdescrive la coordinata sinistra.TRANSLATION_Ydescrive la coordinata superiore.TRANSLATION_Zdescrive la profondità della visualizzazione rispetto alla sua elevazione.
ROTATION,ROTATION_XeROTATION_Y: queste proprietà controllano la rotazione in 2D (proprietàrotation) e in 3D intorno al punto di rotazione.SCROLL_XeSCROLL_Y: queste proprietà indicano l'offset di scorrimento del bordo sinistro e superiore della sorgente in pixel. Indica anche la posizione in termini di scorrimento della pagina.SCALE_XeSCALE_Y: queste proprietà controllano la scalabilità 2D di una visualizzazione intorno al suo punto di pivot.X,YeZ: si tratta di proprietà di utilità di base per descrivere la posizione finale della visualizzazione nel relativo contenitore.Xè la somma del valore a sinistra e diTRANSLATION_X.Yè la somma del valore superiore e diTRANSLATION_Y.Zè la somma del valore di elevazione e diTRANSLATION_Z.
Registra i listener
La classe DynamicAnimation fornisce due
listener: OnAnimationUpdateListener
e OnAnimationEndListener.
Questi listener ascoltano gli aggiornamenti dell'animazione, ad esempio quando
il valore dell'animazione cambia e quando l'animazione termina.
OnAnimationUpdateListener
Quando vuoi animare più viste per creare un'animazione concatenata, puoi
configurare OnAnimationUpdateListener
per ricevere un callback ogni volta che si verifica una modifica nella proprietà
della vista corrente. Il callback notifica all'altra visualizzazione di aggiornare la posizione della molla
in base alla modifica apportata alla proprietà della visualizzazione corrente. Per registrare il
listener, segui questi passaggi:
-
Chiama il metodo
addUpdateListener()e collega il listener all'animazione.Nota:devi registrare il listener di aggiornamento prima dell'inizio dell'animazione. Tuttavia, il listener di aggiornamento deve essere registrato solo se hai bisogno di un aggiornamento per frame sulle modifiche al valore dell'animazione. Un listener di aggiornamento impedisce che l'animazione venga eseguita su un thread separato.
-
Esegui l'override del metodo
onAnimationUpdate()per notificare al chiamante la modifica dell'oggetto corrente. 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
notifica la fine di un'animazione. Puoi configurare il listener in modo che riceva
un 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.
Rimuovere gli ascoltatori
Per interrompere la ricezione dei callback di aggiornamento dell'animazione e dei callback di fine animazione,
chiama i metodi removeUpdateListener()
e removeEndListener(), rispettivamente.
Imposta valore iniziale dell'animazione
Per impostare il valore iniziale dell'animazione, chiama il metodo
setStartValue()
e passa il valore iniziale dell'animazione. Se non imposti il
valore iniziale, l'animazione utilizza il valore corrente della proprietà dell'oggetto
come valore iniziale.
Impostare l'intervallo di valori dell'animazione
Puoi impostare i valori minimo e massimo dell'animazione quando vuoi limitare il valore della proprietà a un determinato intervallo. Inoltre, aiuta a controllare l'intervallo nel caso in cui animi proprietà che hanno un intervallo intrinseco, ad esempio alpha (da 0 a 1).
-
Per impostare il valore minimo, chiama il metodo
setMinValue()e passa il valore minimo della proprietà. -
Per impostare il valore massimo, chiama il metodo
setMaxValue()e passa il valore massimo della proprietà.
Entrambi i metodi restituiscono l'animazione per cui viene impostato il valore.
Nota:se hai impostato il valore iniziale e hai definito un intervallo di valori di animazione, assicurati che il valore iniziale rientri nell'intervallo di valori minimo e massimo.
Imposta velocità iniziale
La velocità iniziale definisce la velocità con cui la proprietà di animazione cambia all'inizio dell'animazione. La velocità iniziale predefinita è impostata su zero pixel al secondo. Puoi impostare la velocità con la velocità dei gesti di tocco 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 poi convertirlo in pixel al secondo. Definire il valore in dp al secondo consente alla velocità di essere indipendente dalla densità e dai fattori di forma. Per ulteriori informazioni sulla conversione del valore in pixel al secondo, consulta la sezione Conversione di dp al secondo in pixel al secondo.
Per impostare la velocità, chiama il metodo
setStartVelocity()
e passa la velocità in pixel al secondo. Il metodo restituisce l'oggetto
forza elastica su cui è impostata la velocità.
Nota:utilizza i metodi delle classi
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 di dp al secondo in pixel al secondo
La velocità di una molla deve essere espressa in pixel al secondo. Se scegli di fornire un valore fisso come inizio della velocità, fornisci il valore in dp al secondo e poi 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());
Imposta le proprietà della molla
La classe SpringForce definisce i metodi getter
e 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 su cui impostare le proprietà. Per saperne di più sulla creazione di una forza elastica personalizzata, consulta la sezione Creazione di una forza elastica personalizzata.
Suggerimento:quando utilizzi i metodi setter, puoi creare una catena di metodi, poiché tutti i metodi setter restituiscono l'oggetto della forza elastica.
Coefficiente di smorzamento
Il rapporto di smorzamento descrive una riduzione graduale dell'oscillazione di una molla. Utilizzando il rapporto di smorzamento, puoi definire la velocità con cui le oscillazioni si attenuano da un rimbalzo all'altro. Esistono quattro modi diversi per smorzare una molla:
- Il sovrasmorzamento si verifica quando il rapporto di smorzamento è maggiore di 1. Consente all'oggetto di tornare delicatamente alla 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 nel minor tempo possibile.
- Il sottosmorzamento si verifica quando il rapporto di smorzamento è inferiore a 1. Consente all'oggetto di superare più volte la posizione di riposo e poi di raggiungerla gradualmente.
- L'assenza di smorzamento si verifica quando il rapporto di smorzamento è uguale a zero. Consente all'oggetto di oscillare all'infinito.
Per aggiungere il rapporto di smorzamento alla molla, segui questi passaggi:
-
Chiama il metodo
getSpring()per recuperare la molla a cui aggiungere il coefficiente di smorzamento. -
Chiama il metodo
setDampingRatio()e passa il coefficiente di smorzamento che vuoi aggiungere alla molla. Il metodo restituisce l'oggetto forza elastica su cui è impostato il coefficiente 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 per sempre.
Nel sistema sono disponibili le seguenti costanti del rapporto di smorzamento:
DAMPING_RATIO_HIGH_BOUNCYDAMPING_RATIO_MEDIUM_BOUNCYDAMPING_RATIO_LOW_BOUNCYDAMPING_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 rigidità definisce la costante elastica, che misura la forza della molla. Una molla rigida applica più forza all'oggetto a cui è collegata quando non è in posizione di riposo. Per aggiungere la rigidità alla molla, segui questi passaggi:
-
Chiama il metodo
getSpring()per recuperare la molla a cui aggiungere la rigidità. -
Chiama il metodo
setStiffness()e passa il valore di rigidità che vuoi aggiungere alla molla. Il metodo restituisce l'oggetto forza elastica su cui è impostata la rigidità.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: rigidità bassa
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 come alternativa all'utilizzo di quella predefinita. La forza elastica personalizzata ti consente di condividere la stessa istanza di forza elastica in più animazioni elastiche. Una volta creata la forza elastica, puoi impostare proprietà come il rapporto di smorzamento e la rigidità.
-
Crea un oggetto
SpringForce.SpringForce force = new SpringForce(); -
Assegna le proprietà chiamando i rispettivi metodi. Puoi anche
creare una catena di metodi.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW); -
Chiama il metodo
setSpring()per impostare la molla sull'animazione.setSpring(force);
Avvia animazione
Esistono due modi per avviare un'animazione con effetto molla: chiamando il metodo
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 è ancora iniziata.
Poiché il metodo aggiorna la posizione finale della molla e avvia l'animazione, se necessario, puoi chiamare questo metodo in qualsiasi momento per modificare il corso di un'animazione. Ad esempio, in un'animazione con effetto molla concatenata, l'animazione
di una visualizzazione dipende da un'altra. Per un'animazione di questo tipo, è più
comodo utilizzare il
metodo animateToFinalPosition(). Se utilizzi questo metodo in un'animazione con effetto molla concatenata, non devi
preoccuparti se l'animazione che vuoi aggiornare successivamente è attualmente in esecuzione.
La figura 10 mostra un'animazione con effetto molla concatenata, in cui l'animazione di una visualizzazione dipende da un'altra visualizzazione.
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 dell'animazione, che si verifica prima del passaggio di disegno.
Di conseguenza, le modifiche vengono riflesse 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 o passare alla fine dell'animazione. Una situazione ideale in cui devi annullare o saltare alla fine dell'animazione si verifica quando l'interazione dell'utente richiede l'interruzione immediata dell'animazione. Ciò accade principalmente quando un utente esce bruscamente da un'app o la visualizzazione diventa invisibile.
Esistono due metodi che puoi utilizzare per terminare l'animazione.
Il metodo cancel()
termina l'animazione al valore in cui si trova. Il metodo
skipToEnd()
salta l'animazione al valore finale e poi la termina.
Prima di poter interrompere 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.
Una volta che conosci lo stato della molla, puoi terminare un'animazione utilizzando il metodo skipToEnd() o il metodo cancel(). Il metodo
cancel()
deve essere chiamato solo sul thread principale.
Nota:in generale, il
metodo skipToEnd() provoca
un salto visivo.