la animación de Android no está terminada en Animation End

Parece que una animación de Android no está realmente terminada cuando el evento onAnimationEnd se onAnimationEnd aunque animation.hasEnded se establece en verdadero.

Quiero que mi vista cambie su fondo dibujable al final de ScaleAnimation , pero se puede ver claramente que se ha cambiado unos milisegundos antes de que termine. El problema es que parpadea porque el nuevo fondo aparece escalado (= es) por un corto tiempo hasta que la animación realmente termina.

¿Hay alguna manera de obtener el final real de la animación o simplemente evitar que el nuevo fondo se escale en este corto período de tiempo?

¡Gracias!


// EDIT: estoy usando un AnimationListener para obtener la siguiente llamada:

  @Override public void onAnimationEnd(Animation animation) { View view = (MyView) ((ExtendedScaleAnimation) animation).getView(); view.clearAnimation(); view.requestLayout(); view.refreshBackground(); // <-- this is where the background gets changed } 

Aquí está el error real relacionado con este problema http://code.google.com/p/android-misc-widgets/issues/detail?id=8

Esto básicamente indica que el método onAnimationEnd no funciona bien cuando un AnimationListener está conectado a una animación

La solución consiste en escuchar los eventos de animación en la vista a la que estaba aplicando la animación. Por ejemplo, si inicialmente estaba conectando el oyente de animación a la animación de esta manera.

 mAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationEnd(Animation arg0) { //Functionality here } }); 

y luego aplicar a la animación a un ImageView como este

 mImageView.startAnimation(mAnimation); 

Para evitar este problema, ahora debe crear un ImageView personalizado

 public class MyImageView extends ImageView { 

y luego anula el método onAnimationEnd de la clase View y proporciona toda la funcionalidad allí

 @Override protected void onAnimationEnd() { super.onAnimationEnd(); //Functionality here } 

Esta es la solución adecuada para este problema, proporcione la funcionalidad en el método View -> onAnimationEnd anterior en lugar del método onAnimationEnd del AnimationListener adjunto a la animación.

Esto funciona correctamente y ya no parpadea hacia el final de la animación. Espero que esto ayude.

Iba a resolver esto llamando a clearAnimation () en la vista animada dentro de AnimationEnd , que eliminó el parpadeo. Es extraño que alguien tenga que hacer eso, ya que en AnimationEnd la callback debería haber sido invocada solo si la animación ya ha finalizado. Pero supongo que la respuesta reside en la profundidad de Framework sobre cómo view / layout maneja la callback de animación. Por ahora tómalo como una solución libre de intrusiones, que simplemente funciona.

  animation.setAnimationListener(new AnimationListener() { public void onAnimationEnd(Animation anim) { innerView.clearAnimation(); // to get rid of flicker at end of animation RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams (innerBlockContainer.getWidth(), innerBlockContainer.getHeight()); /* Update lp margin, left/top to update layout after end of Translation */ ViewGroup parent_ofInnerView = (ViewGroup)innerView.getParent(); vp.updateViewLayout(innerBlockContainer, lp); } public void onAnimationRepeat(Animation arg0) {} public void onAnimationStart(Animation arg0) { } }); innerView.startAnimation(animation); 

Tuve un problema similar y utilicé la solución de Soham con una clase de vista personalizada.

Funcionó bien, pero al final, encontré una solución más simple que funcionó para mí.

Después de llamar a view.StartAnimation(animation) , y antes del siguiente paso en mi progtwig, agregué un breve retraso que será lo suficientemente largo como para permitir que termine la animación, pero lo suficientemente corto como para que el usuario no lo note:

 new Handler().postDelayed(new Runnable() { @Override public void run() { nextStepInMyProgram(); } }, 200);// delay in milliseconds (200) 

Tuve el mismo problema y lo resolví usando

 view.clearAnimation(); 

antes de

 view.startAnimation(anim); 

Por algún motivo, onAnimationStart funciona correctamente y onAnimationEnd no funciona. Entonces aquí está cómo lo hice originalmente y qué cambié:

Intento 1 (parpadeo): a) Mover la imagen de 0px a 80px b) En onAnimationEnd, configure la ubicación de la imagen en 80px

Intento 2 (sin parpadeo): a) En onAnimationStart, establezca la ubicación de la imagen en 80px b) Mueva la imagen de -80px a 0px

Espero que tenga sentido. Básicamente volteé como lo hice

Intenta usar getAnimation () desde tu objeto:

 public void onShowListBtnClick(View view) { rightPanel.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.slide_left)); rightPanel.getAnimation().setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { // write your code here } }); } 

Una solución fácil es agregar una línea a AnimationListener.onAnimationEnd() :

 @Override public void onAnimationEnd(Animation a) { a.setAnimationListener(null); … } 

la anotación también puede detenerse en la rotación de la pantalla. en este caso onAnimationEnd () no se está llamando. mi solución:

  animation.setDuration(animationDuration); animation.setAnimationListener(new AnimationListenerAdapter() {...}); view.startAnimation(animation); handler.postDelayed(new Runnable() { @Override public void run() { if(!animation.hasEnded()) { // here you can handle this case } } }, animationDuration + 100); 

Tuve este problema porque mi Animation no se inició en el hilo principal. Esto dio como resultado una duration de 0. Sin embargo, la Animation sí se onAnimationEnd() correctamente; solo llamó a onAnimationEnd() inmediatamente después de la ejecución.

Si está utilizando el recuento de repeticiones como infinito, entonces no se llamará a AnimationEnd. Verifique el enlace de documentación

Esto funcionó para mí:

 @Override public void onAnimationUpdate(ValueAnimator animation) { if (Float.compare(animation.getAnimatedFraction(),1.0f)) { // animation ended; //do stuff post animation } }