Comment arrêter une animation (annuler () ne fonctionne pas)

245

J'ai besoin d'arrêter une animation de traduction en cours. La .cancel()méthode de Animationn'a aucun effet; l'animation va quand même jusqu'à la fin.

Comment annuler une animation en cours?

Mélanger
la source

Réponses:

509

Appelez clearAnimation()celui que Viewvous avez appelé startAnimation().

CommonsWare
la source
Mais en fait, j'ai besoin d'un truc un peu plus complexe: quand l'animation s'arrête, elle doit rester dans sa position actuelle, c'est-à-dire que j'ai une image glissante et sur un événement tactile, elle doit geler à cet endroit. clearAnimation () n'est pas un cas, car il réinitialise l'état à la position de début / fin en fonction de setFillAfter ()
Mix
1
@ user349871: setFillAfter()ne fait probablement pas ce que vous pensez qu'il fait, de toute façon. Lorsque l'événement tactile se produit, effacez l'animation, puis ajustez votre disposition pour affecter le changement permanent que vous recherchez.
CommonsWare
D'accord, j'essaierai d'arrêter l'animation en appelant clearAnimation (). L'étape suivante consiste à trouver la position de l'animation avant de l'arrêter. Quelle API est pour ça?
Mix
@Mix: Il n'y a pas d'API pour ça.
CommonsWare
7
Re-bonjour! J'ai trouvé un moyen d'obtenir un point (en termes de temps interpolé) lorsque l'animation a été annulée. Vous devez créer une sous-classe Animation et y mettre du code à partir de l'animation de code Android (par exemple TranslateAnimation). Dans votre classe, vous pourrez enregistrer et suivre la position dans la fonction applyTransformation ().
Mix
40

Sur Android 4.4.4, il semble que la seule façon d'arrêter une animation de fondu alpha sur une vue était d'appeler View.animate().cancel()(c'est-à-dire d'appeler .cancel()sur la vue deViewPropertyAnimator ).

Voici le code que j'utilise pour la compatibilité avant et après ICS:

public void stopAnimation(View v) {
    v.clearAnimation();
    if (canCancelAnimation()) {
        v.animate().cancel();
    }
}

... avec la méthode:

/**
 * Returns true if the API level supports canceling existing animations via the
 * ViewPropertyAnimator, and false if it does not
 * @return true if the API level supports canceling existing animations via the
 * ViewPropertyAnimator, and false if it does not
 */
public static boolean canCancelAnimation() {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}

Voici l'animation que j'arrête:

v.setAlpha(0f);
v.setVisibility(View.VISIBLE);
// Animate the content view to 100% opacity, and clear any animation listener set on the view.
v.animate()
    .alpha(1f)
    .setDuration(animationDuration)
    .setListener(null);
Sean Barbeau
la source
.setListener(null);cela m'a aidé.
Muhammad Saqib
18

Si vous utilisez l'écouteur d'animation, définissez v.setAnimationListener(null). Utilisez le code suivant avec toutes les options.

v.getAnimation().cancel();
v.clearAnimation();
animation.setAnimationListener(null);
DjP
la source
2
Il n'est pas nécessaire d'appeler v.setAnimation(null);car cela se fera en v.clearAnimation();.
Christian
Comme @Christian l'a dit, v.setAnimation (null) n'est pas requis
akshay bhange
5

Vous devez utiliser .clearAnimation (); méthode dans le thread d'interface utilisateur:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        v.clearAnimation();
    }
});
rz0
la source
3

Ce que vous pouvez essayer de faire est d'obtenir la matrice de transformation de l'animation avant de l'arrêter et d'inspecter le contenu de la matrice pour obtenir les valeurs de position que vous recherchez.

Voici les API que vous devriez examiner

public boolean getTransformation (long currentTime, Transformation outTransformation)

public Matrix getMatrix ()

public void getValues (float[] values)

Ainsi par exemple (du pseudo code. Je n'ai pas testé ça):

Transformation outTransformation = new Transformation();
myAnimation.getTransformation(currentTime, outTransformation);
Matrix transformationMatrix = outTransformation.getMatrix();
float[] matrixValues = new float[9];
transformationMatrix.getValues(matrixValues);
float transX = matrixValues[Matrix.MTRANS_X];
float transY = matrixValues[Matrix.MTRANS_Y];
Akos Cz
la source
Où obtient-on currentTime?
mako
Oh, la documentation dit qu'elle correspond à "l'horloge murale", ailleurs ils définissent l'horloge murale comme System.currentTimeMillis (), ce qui correspond à l'heure du calendrier et sautera chaque fois que l'heure est modifiée par l'utilisateur ou le réseau. Une mesure étrange à utiliser.
mako
0

Utilisez la méthode setAnimation (null) pour arrêter une animation, elle est exposée comme méthode publique dans View.java , c'est la classe de base pour tous les widgets , qui sont utilisés pour créer des composants d'interface utilisateur interactifs (boutons, champs de texte, etc.). /** * Sets the next animation to play for this view. * If you want the animation to play immediately, use * {@link #startAnimation(android.view.animation.Animation)} instead. * This method provides allows fine-grained * control over the start time and invalidation, but you * must make sure that 1) the animation has a start time set, and * 2) the view's parent (which controls animations on its children) * will be invalidated when the animation is supposed to * start. * * @param animation The next animation, or null. */ public void setAnimation(Animation animation)

saurabh dhillon
la source
0

Pour arrêter l'animation, vous pouvez définir un objet ObjectAnimator qui ne fait rien, par exemple

d'abord lors du retournement manuel, il y a une animation de gauche à droite:

flipper.setInAnimation(leftIn);
flipper.setOutAnimation(rightOut);

puis lors du passage au retournement automatique, il n'y a pas d'animation

flipper.setInAnimation(doNothing);
flipper.setOutAnimation(doNothing);

doNothing = ObjectAnimator.ofFloat(flipper, "x", 0f, 0f).setDuration(flipperSwipingDuration);
Andrew Glukhoff
la source