Animer le mouvement à l'aide d'une animation à effet ressort

Essayer Compose
Jetpack Compose est le kit d'outils d'interface utilisateur recommandé pour Android. Découvrez comment utiliser des animations dans Compose.
<ph type="x-smartling-placeholder"></ph> Spring AnimationSpec →

Basée sur la physique le mouvement est entraîné par la force. La force du ressort est une force qui guide l'interactivité et le mouvement. Les ressorts ayant les caractéristiques suivantes sont les suivants: un amortissement et une raideur. Dans une animation de rétroaction, la valeur et le la vitesse est calculée en fonction de la force exercée sur chaque cadre.

Si vous souhaitez que les animations de votre application ralentissent dans une seule direction, envisagez d'utiliser une méthode animation de glissement d'un geste vif à la place.

Cycle de vie d'une animation de rétroaction

Dans une animation de rétroaction, SpringForce vous permet de personnaliser la raideur du ressort, son taux d'amortissement la position finale. Dès que l'animation commence, la force de ressort la valeur de l'animation et la vitesse sur chaque image. L'animation se poursuit jusqu'à ce que la force du ressort atteigne un équilibre.

Par exemple, si vous faites glisser l'icône d'une application sur l'écran avant de la relâcher en retirant le doigt de l'icône, celle-ci revient à sa version d'origine par une force invisible, mais familière.

La figure 1 illustre un effet de rétroaction similaire. Le signe plus (+) au milieu du cercle indique la force appliquée par un geste tactile.

Version de printemps
Figure 1. Effet de rétroaction

Créer une animation de rétroaction

Pour créer une animation de rétroaction pour votre application, procédez comme suit : comme suit:

Les sections suivantes décrivent les étapes générales de la construction d'un ressort en détail.

Ajouter la bibliothèque Support

Pour utiliser la bibliothèque Support basée sur la physique, vous devez l'ajouter à votre projet comme suit:

  1. Ouvrez le fichier build.gradle du module de votre application.
  2. 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 sur DynamicAnimation sur la page 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 SpringAnimation et indiquez un objet, la propriété d'un objet que vous souhaitez animer et une propriété position finale facultative du ressort à l'endroit où vous souhaitez que l'animation se bloque.

Remarque:Au moment de la création d'une animation de rétroaction, le dernier élément la position du ressort n'est pas obligatoire. Toutefois, 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 le ressort permet d'animer les vues à l'écran en modifiant la 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 de la vue. La valeur est 1 (opaque) par par défaut, la valeur 0 représentant une transparence totale (non visible).
  • TRANSLATION_X, TRANSLATION_Y TRANSLATION_Z: ces propriétés contrôlent l'emplacement de la vue sous la forme d'un delta par rapport à sa gauche la coordonnée supérieure et l'élévation, qui sont définies par sa disposition conteneur.
  • ROTATION, ROTATION_X ROTATION_Y: ces contrôlent la rotation en 2D (propriété rotation) et autour du point pivot en 3D.
  • SCROLL_X et SCROLL_Y: ces indiquent le décalage de défilement de la source, à gauche et en haut en pixels. Il indique également la position de la page. que vous avez fait défiler.
  • SCALE_X et SCALE_Y: ces contrôlent la mise à l'échelle 2D d'une vue autour de son point pivot.
  • X, Y Z: il s'agit des éléments de base des propriétés utilitaires pour décrire l'emplacement final de la vue dans son conteneur.

Enregistrer les écouteurs

La classe DynamicAnimation fournit deux auditeurs: OnAnimationUpdateListener et OnAnimationEndListener. Ces écouteurs écoutent les mises à jour dans l'animation, par exemple lorsqu'un un changement de valeur d'animation et à la fin de l'animation.

OnAnimationUpdateListener

Lorsque vous souhaitez animer plusieurs vues pour créer une animation enchaînée, vous devez peut configurer OnAnimationUpdateListener de recevoir un rappel chaque fois que la vue actuelle est modifiée . Le rappel informe l'autre vue qu'elle doit mettre à jour la position du ressort. en fonction du changement apporté à la propriété de la vue actuelle. Pour enregistrer le procédez comme suit:

  1. Appelez la méthode addUpdateListener(). et associez l'écouteur à l'animation.

    Remarque:Vous devez enregistrer la mise à jour avant le début de l'animation. Toutefois, l'écouteur de mise à jour doit être enregistré uniquement si vous avez besoin d'une mise à jour par image de la valeur de l'animation des modifications. Un écouteur de mise à jour empêche l'animation d'avoir potentiellement s'exécutant sur un thread distinct.

  2. Ignorez onAnimationUpdate() pour informer l'appelant de la modification apportée à l'objet actuel. La L'exemple de code suivant illustre l'utilisation globale OnAnimationUpdateListener

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 chaque fois que l'animation atteint l'équilibre ou est annulée. À enregistrez l'écouteur, procédez comme suit:

  1. Appelez la méthode addEndListener(). et associez l'écouteur à l'animation.
  2. Ignorez onAnimationEnd() pour recevoir une notification chaque fois qu'une animation atteint un équilibre ou est annulée.

Supprimer les écouteurs

Pour ne plus recevoir de rappels de mise à jour d'animation et de rappels de fin d'animation, procédez comme suit : appeler le 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 transmettre la valeur de début de l'animation. Si vous ne définissez pas start, l'animation utilise la valeur actuelle de la propriété de l'objet comme valeur de départ.

Définir la plage de valeurs de l'animation

Vous pouvez définir les valeurs minimale et maximale d'animation lorsque vous souhaitez limiter la valeur de la propriété à une certaine plage. Cela permet également de contrôler 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 transmettre la valeur minimale de la propriété.
  • Pour définir la valeur maximale, appelez la méthode setMaxValue(). et transmettre 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 que vous avez défini une plage de valeurs d'animation, assurez-vous que la valeur de début est comprise dans la la plage de valeurs minimale et maximale.

Définir la vitesse de début

La vitesse de début définit la vitesse à laquelle la propriété d'animation change au début de l'animation. La vitesse de début par défaut est définie sur zéro de pixels par seconde. Vous pouvez définir la vélocité en utilisant la commande tactile ou en utilisant une valeur fixe comme vitesse de départ. Si vous choisissez fournir une valeur fixe, nous vous recommandons de définir la valeur en dp par seconde et puis le convertir en pixels par seconde. Définir la valeur en dp par seconde permet à la vitesse d'être indépendante de la densité et des facteurs de forme. Pour plus des informations sur la conversion de la valeur en pixels par seconde, reportez-vous au Convertir des dp par seconde en pixels par seconde .

Pour définir la vitesse, appelez la méthode setStartVelocity() et transmettre la vitesse en pixels par seconde. La méthode renvoie la force de ressort sur laquelle la vitesse est définie.

Remarque:Utilisez le 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 des dp par seconde en pixels par seconde

La vitesse d'un ressort doit être exprimée en pixels par seconde. Si vous choisissez de fournir une valeur fixe comme début de la vitesse, fournissez la valeur en dp par seconde puis le convertir en pixels par seconde. Pour la conversion, utilisez le applyDimension() de la classe TypedValue. Consultez le 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 le getter. et les méthodes setter pour chacune des propriétés du ressort, telles que l'amortissement le ratio et la raideur. Pour définir les propriétés du ressort, il est important de pour récupérer la force du ressort ou créer une force de ressort personnalisée vous pouvez définir les propriétés. Pour en savoir plus sur la création d'un la force du ressort, reportez-vous à la 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 la force de ressort .

Taux d'amortissement

Le taux d'amortissement décrit une réduction progressive d'une oscillation d'un ressort. Par à l'aide du taux d'amortissement, vous pouvez définir la vitesse à laquelle d'un rebond à l'autre. Il existe quatre façons d'atténuer printemps:

  • Un amortissement excessif se produit lorsque le taux d'amortissement est supérieur à un. Elle permet l'objet revient doucement en position de repos.
  • Un amortissement critique se produit lorsque le taux d'amortissement est égal à un. Elle permet l'objet revient à la position de repos dans les plus brefs délais.
  • Un sous-amortissement se produit lorsque le taux d'amortissement est inférieur à un. Elle permet plusieurs fois de suite en passant la position de repos, arrive progressivement à la position de repos.
  • L'amortissement est activé lorsque le taux d'amortissement est égal à zéro. Elle permet au l'objet oscille indéfiniment.

Pour ajouter le taux d'amortissement au ressort, procédez comme suit:

  1. Appelez la méthode getSpring(). pour récupérer le ressort et ajouter le taux d'amortissement.
  2. Appelez la méthode setDampingRatio(). et transmettez le taux d'amortissement que vous voulez ajouter au ressort. La 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 réglez le taux d'amortissement sur zéro, le ressort n'atteignent jamais la position de repos. En d'autres termes, il oscille indéfiniment.

Les constantes de taux d'amortissement suivantes sont disponibles dans le système:

Figure 2: Rebond élevé

Figure 3: Rebond moyen

Figure 4: Rebond faible

Figure 5: Pas de rebond

Le taux d'amortissement par défaut est de 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 plus de force à l'objet fixé. lorsque le ressort n'est pas en position de repos. Pour renforcer la raideur du ressort, procédez comme suit:

  1. Appelez la méthode getSpring(). pour récupérer le ressort et ajouter la raideur.
  2. Appelez la méthode setStiffness(). et transmettre la valeur de raideur que vous souhaitez ajouter au ressort. La renvoie l'objet force de ressort sur lequel la raideur est définie.

    Remarque:La raideur doit être un paramètre 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 par défaut la force du ressort. La force de ressort personnalisée vous permet de partager la même force de ressort. dans plusieurs animations de rétroaction. Une fois que vous avez créé vous pouvez définir des propriétés telles que le taux d'amortissement et la raideur.

  1. Créer un objet SpringForce.

    SpringForce force = new SpringForce();

  2. 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);

  3. Appelez la méthode setSpring(). pour définir le rebond sur l'animation.

    setSpring(force);

Lancer l'animation

Il existe deux façons de lancer une animation de rétroaction: en appelant la méthode 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 elle n'a pas démarré.

Puisque la méthode met à jour la position finale du ressort et lance la l'animation si nécessaire, vous pouvez appeler cette méthode à 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 ce qui vous permet d'utiliser animateToFinalPosition() . En utilisant cette méthode dans une animation de rétroaction en chaîne, vous n'avez pas besoin vous demander 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'un dépend d'une autre vue.

<ph type="x-smartling-placeholder">
</ph> Démonstration de printemps en chaîne
Figure 10. Démonstration de l'enchaînement du ressort

Pour utiliser animateToFinalPosition() , appelez la méthode animateToFinalPosition() puis faites passer le ressort en position de repos. Vous pouvez aussi définir le reste du ressort en appelant la méthode setFinalPosition() .

La méthode start() effectue ne pas définir immédiatement la valeur de la propriété sur la valeur de départ. La propriété change à chaque impulsion de l'animation, ce qui se produit avant le dessin. Les modifications sont donc répercutées dans l'image suivante, les valeurs sont 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. Une situation idéale où vous devez annuler ou passer à la fin de l'interaction, c'est-à-dire lorsqu'un utilisateur interaction exige que l'animation s'arrête immédiatement. C'est 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 à 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 amorcé, l'animation ne peut jamais atteindre en position de repos. Pour vérifier l'état du ressort, appelez la méthode canSkipToEnd(). Si le ressort est amorti, la méthode renvoie true. Sinon, false

Une fois que vous connaissez l'état du ressort, vous pouvez arrêter une animation en utilisant skipToEnd() ou la cancel(). La cancel() méthode doit être appelé uniquement sur le thread principal.

Remarque:En général, Causes de la méthode skipToEnd() un saut visuel.