2010-06-11 21 views
21

Sto creando un gioco e mi piacerebbe mostrare un semplice "spartito" -animazione al giocatore quando gli vengono dati dei crediti. Questa è la vista butto sullo schermo:Come rimuovere una vista al termine dell'animazione?

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(); 
    } 
    }; 
} 

Questo codice in realtà funziona abbastanza bene finché c'è un solo animazione punteggio sullo schermo in un dato momento. Se il giocatore segna ancora, prima che l'ultimo punteggio fosse rimosso, l'app si arresta in modo anomalo, probabilmente perché il secondo punteggio ottiene l'evento da rimuovere durante l'animazione. È una cattiva pratica dell'utilizzo dell'animazione? Come gestireste questo ragazzi?

risposta

35

Ho anche scoperto che quando si rimuove una vista dal suo genitore dopo aver applicato un'animazione a questa vista (usando onAnimationEnd) si blocca con NPE sul dispatchDraw del genitore.

L'unica soluzione che ho trovato è di attivare la rimozione all'interno di una chiamata post. Normalmente tutte le modifiche dell'interfaccia utente devono essere eseguite sul thread dell'interfaccia utente, quindi ho aggiunto una chiamata runOnUiThread sull'attività, ma potrebbe essere inutile (funziona senza di me).

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

il 'runOnUiThread' non è necessario. Fare un post in una vista renderà la corsa eseguibile nel thread ui. – Macarse

+1

Grazie, mi sono imbattuto in questo stesso errore e la pubblicazione sulla vista mi ha permesso di rimuovere le viste. È _weird_ che un listener di animazione non sia in esecuzione nel thread dell'interfaccia utente ... –

+5

penso che sia già in esecuzione sul thread dell'interfaccia utente. Una possibile ragione per cui post() funziona (questa è solo un'ipotesi) è che se si rimuove la vista direttamente nei metodi del listener di animazione, questi verranno chiamati prima dell'esecuzione della logica di disegno e si verificherà l'NPE. Ad esempio, ogni vista può avere il suo stato anim aggiornato prima del disegno e, se l'animazione è finita, i metodi del listener vengono richiamati. Quando si registra un eseguibile, questo verrà accodato dal looper che probabilmente non elaborerà alcun messaggio fino a quando la logica di aggiornamento della gerarchia della vista non sarà terminata per questo frame. Potrebbe essere tutto filo ui – Dori

0

Quando si utilizza AnimationUtils.loadAnimation view.clearAnimation() Ha risolto il problema

Problemi correlati