Cómo detener una animación (cancel () no funciona)

244

Necesito detener una animación de traducción en ejecución. El .cancel()método de Animationno tiene efecto; la animación va hasta el final de todos modos.

¿Cómo cancelas una animación en ejecución?

Mezcla
fuente

Respuestas:

508

Llamar clearAnimation()en lo Viewque llamó startAnimation().

CommonsWare
fuente
Pero, de hecho, necesito algo un poco más complejo: cuando la animación se detiene, debe permanecer en la posición actual, es decir, tengo una imagen deslizante y, en caso de contacto, debe congelarse en este lugar. clearAnimation () no es un caso, porque restablece el estado a la posición de inicio / finalización según setFillAfter ()
Mezcle el
1
@ user349871: de setFillAfter()todos modos, probablemente no haga lo que crees que hace. Cuando ocurra el evento táctil, borre la animación y luego ajuste su diseño para afectar cualquier cambio permanente que busque.
CommonsWare
Ok, bien, intentaré detener la animación llamando a clearAnimation (). El siguiente paso es encontrar la posición donde ha estado la animación antes de detenerla. ¿Qué API es para eso?
Mezclar
@Mix: no hay API para eso.
CommonsWare
77
¡Hola de nuevo! He encontrado una manera de obtener puntos (en términos de tiempo interpolado) cuando se canceló la animación. Debe crear una subclase de animación y colocar el código de la animación de código de Android (por ejemplo, TranslateAnimation). En su clase podrá guardar y rastrear la posición en la función applyTransformation ().
Mezclar
40

En Android 4.4.4, parece que la única forma en que podría detener una animación de desvanecimiento alfa en una Vista fue llamando View.animate().cancel()(es decir, llamando .cancel()a la Vista ViewPropertyAnimator).

Aquí está el código que estoy usando para compatibilidad antes y después de ICS:

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

... con el método:

/**
 * 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;
}

Aquí está la animación que estoy deteniendo:

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
fuente
.setListener(null);Esto me ayudó.
Muhammad Saqib
18

Si está utilizando el oyente de animación, establezca v.setAnimationListener(null). Use el siguiente código con todas las opciones.

v.getAnimation().cancel();
v.clearAnimation();
animation.setAnimationListener(null);
DjP
fuente
2
No es necesario llamar v.setAnimation(null);porque esto se hará en v.clearAnimation();.
Christian
Como @Christian dijo v.setAnimation (nulo) no es obligatorio
akshay bhange
5

Debe usar .clearAnimation (); método en el hilo de la interfaz de usuario:

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

Lo que puede intentar hacer es obtener la matriz de transformación de la animación antes de detenerla e inspeccionar el contenido de la matriz para obtener los valores de posición que está buscando.

Aquí están las API que deberías mirar

public boolean getTransformation (long currentTime, Transformation outTransformation)

public Matrix getMatrix ()

public void getValues (float[] values)

Entonces, por ejemplo (algunos pseudocódigo. No he probado esto):

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
fuente
¿Dónde obtenemos currentTime?
mako
Ah, la documentación dice que corresponde al "reloj de pared", en otro lugar definen el reloj de pared como System.currentTimeMillis (), que corresponde al tiempo del calendario y saltará cada vez que el usuario o la red cambien la hora. Una medida extraña para usar.
mako
0

Use el método setAnimation (nulo) para detener una animación, expuesta como método público en View.java , es la clase base para todos los widgets , que se utilizan para crear componentes interactivos de la interfaz de usuario (botones, campos de texto, 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
fuente
0

Para detener la animación, puede establecer un objeto ObjectAnimator que no haga nada, p. Ej.

primero cuando el volteo manual hay animación de izquierda a derecha:

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

luego, al cambiar a cambio automático, no hay animación

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

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