programacion - la animación de Android no está terminada en Animation End
manual de programacion android pdf (11)
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.
Esto funcionó para mí:
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if (Float.compare(animation.getAnimatedFraction(),1.0f)) {
// animation ended;
//do stuff post animation
}
}
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 devolución de llamada 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 devolución de llamada 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);
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
}
});
}
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
Si está utilizando el recuento de repeticiones como infinito, entonces no se llamará a AnimationEnd. Verifique el link documentación
Tuve el mismo problema y lo resolví usando
view.clearAnimation();
antes de
view.startAnimation(anim);
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.
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 programa, 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)
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);