Como parar uma animação (cancel () não funciona)

244

Preciso parar uma animação de tradução em execução. O .cancel()método de Animationnão tem efeito; a animação vai até o fim de qualquer maneira.

Como você cancela uma animação em execução?

Misturar
fonte

Respostas:

508

Ligue clearAnimation()para onde Viewvocê ligou startAnimation().

CommonsWare
fonte
Mas, de fato, preciso de algo um pouco mais complexo: quando a animação para, ela deve permanecer na posição atual, ou seja, eu tenho uma imagem deslizante e um evento ao toque deve congelar neste local. clearAnimation () não é um caso, pois redefine o estado para a posição inicial / final, dependendo de setFillAfter ()
Mix
1
@ user349871: setFillAfter()provavelmente não faz o que você pensa que faz. Quando o evento de toque ocorrer, limpe a animação e ajuste seu layout para afetar qualquer alteração permanente que você deseja.
CommonsWare
Ok, bom, tentarei interromper a animação chamando clearAnimation (). O próximo passo é encontrar a posição onde a animação esteve antes de eu pará-la. Qual API é para isso?
Misture
@ Mix: Não há API para isso.
CommonsWare
7
Oi de novo! Eu encontrei uma maneira de obter um ponto (em termos de tempo interpolado) quando a animação era cancelada. Você precisa criar a subclasse Animação e inserir o código da animação do código do Android (por exemplo, TranslateAnimation). Na sua turma, você poderá salvar e rastrear a posição na função applyTransformation ().
Misture
40

No Android 4.4.4, parece que a única maneira de parar uma animação de desbotamento alfa em um View era a chamada View.animate().cancel()(ou seja, a chamada .cancel()da View ViewPropertyAnimator).

Aqui está o código que estou usando para compatibilidade antes e depois do ICS:

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

... com o 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;
}

Aqui está a animação que estou parando:

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
fonte
.setListener(null);isso me ajudou.
Muhammad Saqib
18

Se você estiver usando o ouvinte de animação, defina v.setAnimationListener(null). Use o seguinte código com todas as opções.

v.getAnimation().cancel();
v.clearAnimation();
animation.setAnimationListener(null);
DjP
fonte
2
Não é necessário ligar v.setAnimation(null);porque isso será feito em v.clearAnimation();.
Christian
Como @Christian disse v.setAnimation (null) não é necessária
akshay Bhange
5

Você deve usar .clearAnimation (); método no thread da interface do usuário:

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

O que você pode tentar fazer é obter a matriz de transformação da animação antes de pará-la e inspecionar o conteúdo da matriz para obter os valores de posição que você está procurando.

Aqui estão as APIs que você deve procurar

public boolean getTransformation (long currentTime, Transformation outTransformation)

public Matrix getMatrix ()

public void getValues (float[] values)

Então, por exemplo (algum pseudo-código. Eu não testei isso):

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
fonte
Onde obtemos currentTime?
mako
Ah, a documentação diz que corresponde ao "relógio de parede"; em outros lugares, eles definem o relógio de parede como System.currentTimeMillis (), que corresponde ao tempo do calendário e salta sempre que o horário ou o usuário é alterado pela rede. Uma medida ímpar para usar.
mako
0

Use o método setAnimation (null) para interromper uma animação, exposta como método público em View.java , é a classe base de todos os widgets , usados ​​para criar componentes interativos da interface do usuário (botões, 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
fonte
0

Para interromper a animação, você pode definir o objectAnimator que não faz nada, por exemplo

primeiro, ao virar manualmente, há animação da esquerda para a direita:

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

quando mudar para inversão automática, não há animação

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

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