Le mouvement basé sur la physique est stimulé par la force. La force de ressort est l'une de ces forces qui guident l'interactivité et le mouvement. Une force de ressort présente les propriétés suivantes : amortissement et raideur. Dans une animation basée sur le ressort, la valeur et la vitesse sont calculées en fonction de la force de tension appliquée à chaque image.
Si vous souhaitez que les animations de votre application ralentissent dans une seule direction, utilisez plutôt une animation de déplacement basée sur des frictions.
Cycle de vie d'une animation de rétroaction
Dans une animation basée sur les ressorts, la classe SpringForce
vous permet de personnaliser la raideur du ressort, son taux d'amortissement et sa position finale. Dès le début de l'animation, la force de ressort met à jour la valeur de l'animation et la vitesse de chaque image. L'animation se poursuit jusqu'à ce que la force de tension atteigne un équilibre.
Par exemple, si vous faites glisser une icône d'application sur l'écran, puis relâchez-la en levant le doigt dessus, celle-ci revient à son emplacement d'origine grâce à une force invisible mais familière.
La figure 1 illustre un effet de ressort similaire. Le signe plus (+) au milieu du cercle indique la force appliquée par un geste tactile.
Créer une animation de rétroaction
Pour créer une animation de rétroaction pour votre application, procédez comme suit:
- Ajouter la bibliothèque Support Vous devez ajouter la bibliothèque Support à votre projet pour utiliser les classes d'animation de rétroaction.
- Créer une animation de rétroaction:l'étape principale consiste à créer une instance de la classe
SpringAnimation
et à définir les paramètres de comportement du mouvement. - (Facultatif) Enregistrer des écouteurs:enregistrez des écouteurs pour surveiller les modifications apportées au cycle de vie des animations et les mises à jour de leurs valeurs.
Remarque:L'écouteur de mise à jour ne doit être enregistré que si vous avez besoin d'une mise à jour par image en cas de modification de la valeur de l'animation. Un écouteur de mise à jour empêche l'exécution potentielle de l'animation sur un thread distinct.
- (Facultatif) Supprimer les écouteurs:supprimez les écouteurs qui ne sont plus utilisés.
- (Facultatif) Définir une valeur de début:personnalisez la valeur de début de l'animation.
- (Facultatif) Définir une plage de valeurs:définissez la plage de valeurs de l'animation pour qu'elle restreigne les valeurs entre la valeur minimale et la plage maximale.
- (Facultatif) Définir la vitesse de début:définissez la vitesse de début de l'animation.
- (Facultatif) Définissez les propriétés du ressort:Définissez le taux d'amortissement et la raideur du ressort.
- (Facultatif) Créer un ressort personnalisé:créez un ressort personnalisé si vous n'avez pas l'intention d'utiliser le ressort par défaut ou si vous souhaitez utiliser un ressort commun tout au long de l'animation.
- Démarrer l'animation:lance l'animation de rétroaction.
- (Facultatif) Annuler l'animation:annulez l'animation si l'utilisateur quitte brusquement l'application ou si la vue devient invisible.
Les sections suivantes décrivent en détail les étapes générales de création d'une animation de rétroaction.
Ajouter la bibliothèque Support
Pour utiliser la bibliothèque Support basée sur la physique, vous devez l'ajouter à votre projet comme suit:
- Ouvrez le fichier
build.gradle
du module de votre application. Ajoutez la bibliothèque Support à la section
dependencies
.Groovy
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") }
Pour afficher les versions actuelles de cette bibliothèque, consultez les informations concernant DynamicAnimation sur la page des versions.
Créer une animation de rétroaction
La classe SpringAnimation
vous permet de créer une animation de rétroaction pour un objet. Pour créer une animation de rétroaction, vous devez créer une instance de la classe SpringAnimation
et fournir un objet, la propriété d'un objet que vous souhaitez animer et, si vous le souhaitez, une position de ressort finale à l'endroit où vous souhaitez que l'animation repose.
Remarque:Au moment de la création d'une animation de rétroaction, la position finale du ressort est facultative. Cependant, il doit être défini avant de lancer l'animation.
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'animation basée sur les ressorts peut animer des vues à l'écran en modifiant les propriétés réelles des objets de vue. Les vues suivantes sont disponibles dans le système:
ALPHA
: représente la transparence alpha sur la vue. La valeur est 1 (opaque) par défaut, et la valeur 0 correspond à une transparence totale (non visible).TRANSLATION_X
,TRANSLATION_Y
etTRANSLATION_Z
: ces propriétés contrôlent l'emplacement de la vue sous la forme d'un delta par rapport à sa coordonnée gauche, sa coordonnée supérieure et son altitude, qui sont définies par son conteneur de mise en page.TRANSLATION_X
décrit la coordonnée de gauche.TRANSLATION_Y
décrit la coordonnée supérieure.TRANSLATION_Z
décrit la profondeur de la vue par rapport à son élévation.
ROTATION
,ROTATION_X
etROTATION_Y
: ces propriétés contrôlent la rotation en 2D (propriétérotation
) et en 3D autour du point pivot.SCROLL_X
etSCROLL_Y
: ces propriétés indiquent le décalage de défilement de la source, vers la gauche et le bord supérieur, en pixels. Elle indique également la position en termes de défilement de la page.SCALE_X
etSCALE_Y
: ces propriétés contrôlent la mise à l'échelle 2D d'une vue autour de son point pivot.X
,Y
etZ
: ces propriétés utilitaires de base décrivent l'emplacement final de la vue dans son conteneur.X
est la somme de la valeur de gauche et deTRANSLATION_X
.Y
est la somme de la valeur la plus élevée et deTRANSLATION_Y
.Z
est la somme de la valeur d'altitude et deTRANSLATION_Z
.
Enregistrer des écouteurs
La classe DynamicAnimation
fournit deux écouteurs: OnAnimationUpdateListener
et OnAnimationEndListener
.
Ces écouteurs écoutent les mises à jour de l'animation, par exemple en cas de changement de la valeur de l'animation et lorsque celle-ci se termine.
OnAnimationUpdateListener
Lorsque vous souhaitez animer plusieurs vues pour créer une animation en chaîne, vous pouvez configurer OnAnimationUpdateListener
pour qu'il reçoive un rappel chaque fois que la propriété de la vue actuelle est modifiée. Le rappel informe l'autre vue qu'elle doit mettre à jour sa position de ressort en fonction du changement apporté à la propriété de la vue actuelle. Pour enregistrer l'écouteur, procédez comme suit:
-
Appelez la méthode
addUpdateListener()
et associez l'écouteur à l'animation.Remarque:Vous devez enregistrer l'écouteur de mise à jour avant le début de l'animation. Toutefois, l'écouteur de mise à jour ne doit être enregistré que si vous avez besoin d'une mise à jour par image en cas de modification de la valeur de l'animation. Un écouteur de mise à jour empêche l'exécution potentielle de l'animation sur un thread distinct.
-
Ignorez la méthode
onAnimationUpdate()
pour informer l'appelant de la modification de l'objet actuel. L'exemple de code suivant illustre l'utilisation globale deOnAnimationUpdateListener
.
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
notifie la fin d'une animation. Vous pouvez configurer l'écouteur pour recevoir un rappel chaque fois que l'animation atteint l'équilibre ou qu'elle est annulée. Pour enregistrer l'écouteur, procédez comme suit:
-
Appelez la méthode
addEndListener()
et associez l'écouteur à l'animation. -
Ignorez la méthode
onAnimationEnd()
pour recevoir une notification chaque fois qu'une animation atteint l'équilibre ou est annulée.
Supprimer les écouteurs
Pour arrêter de recevoir des rappels de mise à jour de l'animation et des rappels de fin d'animation, appelez respectivement les méthodes removeUpdateListener()
et removeEndListener()
.
Définir la valeur de début de l'animation
Pour définir la valeur de début de l'animation, appelez la méthode setStartValue()
et transmettez la valeur de début de l'animation. Si vous ne définissez pas la valeur de début, l'animation utilise la valeur actuelle de la propriété de l'objet comme valeur de début.
Définir la plage de valeurs de l'animation
Vous pouvez définir les valeurs minimale et maximale de l'animation lorsque vous souhaitez restreindre la valeur de la propriété à une certaine plage. Il est également utile de contrôler la plage si vous animez des propriétés ayant une plage intrinsèque, comme alpha (de 0 à 1).
-
Pour définir la valeur minimale, appelez la méthode
setMinValue()
et transmettez la valeur minimale de la propriété. -
Pour définir la valeur maximale, appelez la méthode
setMaxValue()
et transmettez la valeur maximale de la propriété.
Les deux méthodes renvoient l'animation pour laquelle la valeur est définie.
Remarque:Si vous avez défini la valeur de début et défini une plage de valeurs pour l'animation, assurez-vous que la valeur de début se situe entre les valeurs minimale et maximale.
Définir la vitesse de départ
La vitesse de début définit la vitesse à laquelle la propriété de l'animation change au début de l'animation. La vitesse de démarrage par défaut est définie sur zéro pixel par seconde. Vous pouvez définir la vitesse avec la vitesse des gestes tactiles ou en utilisant une valeur fixe comme vitesse de départ. Si vous choisissez de fournir une valeur fixe, nous vous recommandons de la définir en dp par seconde, puis de la convertir en pixels par seconde. En définissant la valeur en dp par seconde, la vitesse peut être indépendante de la densité et des facteurs de forme. Pour en savoir plus sur la conversion d'une valeur en pixels par seconde, consultez la section Convertir des dp par seconde en pixels par seconde.
Pour définir la vitesse, appelez la méthode setStartVelocity()
et transmettez la vitesse en pixels par seconde. La méthode renvoie l'objet de force de tension sur lequel la vitesse est définie.
Remarque:Utilisez les méthodes de classe GestureDetector.OnGestureListener
ou VelocityTracker
pour récupérer et calculer la vitesse des gestes tactiles.
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);
Conversion de dp par seconde en pixels par seconde
La vélocité d'un ressort doit être exprimée en pixels par seconde. Si vous choisissez de fournir une valeur fixe comme point de départ de la vitesse, indiquez la valeur en dp par seconde, puis convertissez-la en pixels par seconde. Pour la conversion, utilisez la méthode applyDimension()
de la classe TypedValue
. Consultez l'exemple de code suivant:
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());
Définir les propriétés du ressort
La classe SpringForce
définit les méthodes "getter" et "setter" pour chacune des propriétés de ressort, telles que le taux d'amortissement et la raideur. Pour définir les propriétés du ressort, il est important de récupérer l'objet de force de ressort ou de créer une force de ressort personnalisée sur laquelle vous pouvez définir les propriétés. Pour plus d'informations sur la création d'une force de ressort personnalisée, consultez la section Créer une force de ressort personnalisée.
Conseil:Lorsque vous utilisez les méthodes setter, vous pouvez créer une chaîne de méthodes, car toutes les méthodes setter renvoient l'objet de force de tension.
Taux d'amortissement
Le taux d'amortissement décrit une réduction progressive de l'oscillation du ressort. En utilisant le taux d'amortissement, vous pouvez définir la vitesse à laquelle les oscillations diminuent d'un rebond à l'autre. Vous pouvez amortir un ressort de quatre manières différentes:
- Le suramortissement se produit lorsque le taux d'amortissement est supérieur à un. Cela permet à l'objet de se remettre doucement en position au repos.
- L'amortissement critique se produit lorsque le taux d'amortissement est égal à un. Elle permet à l'objet de revenir à sa position au repos dans le délai le plus court.
- Le sous-amortissement se produit lorsque le taux d'amortissement est inférieur à un. Elle permet à l'objet de dépasser plusieurs fois en transmettant la position de repos, puis d'atteindre progressivement cette position.
- Elle se produit lorsque le taux d'amortissement est égal à zéro. Elle permet à l'objet d'osciller indéfiniment.
Pour ajouter le taux d'amortissement au ressort, procédez comme suit:
-
Appelez la méthode
getSpring()
pour récupérer le ressort afin d'ajouter le taux d'amortissement. -
Appelez la méthode
setDampingRatio()
et transmettez le taux d'amortissement que vous souhaitez ajouter au ressort. Cette méthode renvoie l'objet de force de ressort sur lequel le taux d'amortissement est défini.Remarque:Le taux d'amortissement doit être un nombre non négatif. Si vous définissez le taux d'amortissement sur zéro, le ressort n'atteindra jamais sa position au repos. En d'autres termes, il oscille indéfiniment.
Les constantes de taux d'amortissement suivantes sont disponibles dans le système:
DAMPING_RATIO_HIGH_BOUNCY
DAMPING_RATIO_MEDIUM_BOUNCY
DAMPING_RATIO_LOW_BOUNCY
DAMPING_RATIO_NO_BOUNCY
Figure 2: Rebond élevé
Figure 3: Rebond moyen
Figure 4: Rebond faible
Figure 5: Aucun rebond
Le taux d'amortissement par défaut est défini sur 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); …
Raideur
La raideur définit la constante du ressort, qui mesure la force du ressort. Un ressort rigide applique une plus grande force à l'objet fixé lorsque le ressort n'est pas en position au repos. Pour renforcer la raideur du ressort, procédez comme suit:
-
Appelez la méthode
getSpring()
pour récupérer le ressort afin d'ajouter la raideur. -
Appelez la méthode
setStiffness()
et transmettez la valeur de raideur que vous souhaitez ajouter au ressort. Cette méthode renvoie l'objet de force de ressort sur lequel la raideur est définie.Remarque:La raideur doit être un nombre positif.
Les constantes de raideur suivantes sont disponibles dans le système:
Figure 6: Raideur élevée
Figure 7: Raideur moyenne
Figure 8: Faible raideur
Figure 9: Raideur très faible
La raideur par défaut est définie sur 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); …
Créer une force de ressort personnalisée
Vous pouvez créer une force de ressort personnalisée au lieu d'utiliser la force de ressort par défaut. La force de ressort personnalisée vous permet de partager la même instance de force de ressort entre plusieurs animations de ressort. Une fois que vous avez créé la force de ressort, vous pouvez définir des propriétés telles que le taux d'amortissement et la raideur.
-
Créer un objet
SpringForce
.SpringForce force = new SpringForce();
-
Attribuez les propriétés en appelant les méthodes correspondantes. Vous pouvez également créer une chaîne de méthodes.
force.setDampingRatio(DAMPING_RATIO_LOW_BOUNCY).setStiffness(STIFFNESS_LOW);
-
Appelez la méthode
setSpring()
pour définir le ressort sur l'animation.setSpring(force);
Démarrer l'animation
Vous pouvez démarrer une animation de rétroaction de deux manières: en appelant start()
ou en appelant la méthode animateToFinalPosition()
. Les deux méthodes doivent être appelées sur le thread principal.
animateToFinalPosition()
effectue deux tâches:
- Définit la position finale du ressort.
- Lance l'animation, si ce n'est pas déjà fait.
Étant donné qu'elle met à jour la position finale du ressort et lance l'animation si nécessaire, vous pouvez l'appeler à tout moment pour modifier le cours d'une animation. Par exemple, dans une animation de rétroaction en chaîne, l'animation d'une vue dépend d'une autre vue. Pour une telle animation, il est plus pratique d'utiliser la méthode animateToFinalPosition()
. En utilisant cette méthode dans une animation de rétroaction en chaîne, vous n'avez pas à vous soucier si l'animation que vous souhaitez mettre à jour est en cours d'exécution.
La figure 10 illustre une animation de rétroaction en chaîne, où l'animation d'une vue dépend d'une autre vue.
Pour utiliser la méthode animateToFinalPosition()
, appelez la méthode animateToFinalPosition()
et transmettez la position reste du ressort. Vous pouvez également définir la position de repos du ressort en appelant la méthode setFinalPosition()
.
La méthode start()
ne définit pas immédiatement la valeur de la propriété sur la valeur de début. La valeur de la propriété change à chaque impulsion de l'animation, ce qui se produit avant la fin du dessin.
Par conséquent, les modifications sont reflétées dans le frame suivant, comme si les valeurs étaient définies immédiatement.
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(); …
Annuler l'animation
Vous pouvez annuler l'animation ou passer à la fin. Idéalement, vous devez annuler l'ami ou passer directement à la fin lorsqu'une interaction de l'utilisateur exige l'arrêt immédiat de l'animation. Cela se produit principalement lorsqu'un utilisateur quitte brusquement une application ou que la vue devient invisible.
Vous pouvez utiliser deux méthodes pour arrêter l'animation.
La méthode cancel()
met fin à l'animation sur la valeur où elle se trouve. La méthode skipToEnd()
ignore l'animation jusqu'à la valeur finale, puis l'arrête.
Avant de pouvoir arrêter l'animation, il est important de vérifier l'état du ressort. Si l'état n'est pas amorti, l'animation ne pourra jamais atteindre la position repos.
Pour vérifier l'état du ressort, appelez la méthode canSkipToEnd()
. Si le ressort est amorti, la méthode renvoie true
. Sinon, elle renvoie false
.
Une fois que vous connaissez l'état du ressort, vous pouvez arrêter une animation à l'aide de la méthode skipToEnd()
ou cancel()
. La méthode cancel()
doit être appelée uniquement sur le thread principal.
Remarque:En général, la méthode skipToEnd()
provoque un saut visuel.