2010-06-11 7 views
21

Estoy creando un juego y me gustaría mostrar una simple "puntuación" -animación para el jugador cuando se le otorgan créditos. Esta es la vista que lanzo en la pantalla:¿Cómo eliminar una vista cuando termina la animación?

public class Score extends FrameLayout { 

    public Score(Context context, int score) { 
    super(context); 
    TextView txt = new TextView(context); 
    txt.setText(String.valueOf(score).toUpperCase()); 
    addView(txt); 
    Animation anim = AnimationUtils.loadAnimation(context, R.anim.score); 
    startAnimation(anim); 
    anim.setAnimationListener(animationListener); 
    } 
    private void Remove(){ 

    ViewGroup parent = (ViewGroup)getParent(); 
    parent.removeView(this); 

    } 
    private AnimationListener animationListener = new AnimationListener() { 

    @Override 
    public void onAnimationEnd(Animation animation) { 

     Remove(); 
    } 
    }; 
} 

Este código en realidad funciona bastante bien, siempre y cuando sólo hay un puntaje de animación en la pantalla en un momento dado. Si el jugador marca nuevamente, antes de que se elimine el último puntaje, la aplicación se bloquea, probablemente porque el segundo puntaje hace que el evento se elimine durante la animación. ¿Es esta una mala práctica de usar Animación? ¿Cómo manejarían esto?

Respuesta

35

También encontré que al eliminar una vista de su padre después de aplicar una animación a esta vista (usando onAnimationEnd) se bloquea con NPE en el dibujo de envío del padre.

La única solución que encontré es activar la eliminación dentro de una llamada posterior. Normalmente, todas las modificaciones de la interfaz de usuario se deben realizar en la secuencia de la interfaz de usuario, por lo que agregué una llamada runOnUiThread a la actividad, pero podría ser inútil (a mí me funciona sin eso).

Animation animation = AnimationUtils.loadAnimation(parentView.getContext(), animationId); 
animation.setAnimationListener(new AnimationListener() { 
    public void onAnimationStart(Animation paramAnimation) { } 
    public void onAnimationRepeat(Animation paramAnimation) { } 
    public void onAnimationEnd(Animation paramAnimation) { 
     // without the post method, the main UI crashes if the view is removed 
     parentView.post(new Runnable() { 
      public void run() { 
       // it works without the runOnUiThread, but all UI updates must 
       // be done on the UI thread 
       activity.runOnUiThread(new Runnable() { 
        public void run() { 
         parentView.removeView(view); 
        } 
       }); 
      } 
     }); 
    } 
}); 

view.setVisibility(visibility()); 
view.startAnimation(animation); 
+13

el 'runOnUiThread' no es necesario. Hacer una publicación en una vista hará que el ejecutable se ejecute en el hilo de la interfaz de usuario. – Macarse

+1

Gracias, me encontré con este mismo error y publicar en la vista me permitió eliminar las vistas. Es extraño que un oyente de animación no se esté ejecutando en el hilo de la interfaz de usuario ... –

+5

, creo que ya se está ejecutando en el hilo de la interfaz de usuario. Una posible razón por la que post() funciona (esto es solo una suposición) es que si elimina la vista directamente en los métodos de escucha de animación, se invocará antes de que se ejecute la lógica de extracción y se encontrará con el NPE. Por ejemplo, cada vista puede tener su estado anim actualizado antes de dibujar, y si el anim finaliza sus métodos de escucha se llaman. Cuando publica un ejecutable, el enrutador lo pondrá en cola, lo que probablemente no procesará ningún mensaje hasta que la vista de actualización de jerarquía/lógica de dibujo haya finalizado para este marco. Podría ser todo un hilo – Dori

0

Al utilizar AnimationUtils.loadAnimation view.clearAnimation() resuelto mi problema

Cuestiones relacionadas