wake-up-neo.com

android-Animation ist in onAnimationEnd nicht abgeschlossen

Es scheint, dass eine Android-Animation nicht wirklich beendet ist, wenn das Ereignis onAnimationEnd ausgelöst wird, obwohl animation.hasEnded auf true gesetzt ist.

Ich möchte, dass meine Ansicht am Hintergrund ihrer ScaleAnimation-Zeichnung gezeichnet wird. Sie kann jedoch deutlich sehen, dass sie einige Millisekunden vor dem Ende geändert wird. Das Problem ist, dass es flackert, weil der neue Hintergrund kurzzeitig skaliert erscheint (= ist), bis die Animation wirklich beendet ist.

Gibt es eine Möglichkeit, entweder das eigentliche Ende der Animation zu erhalten oder einfach zu verhindern, dass der neue Hintergrund in dieser kurzen Zeit skaliert wird?

Vielen Dank!


// EDIT: Ich verwende eine AnimationListener, um den folgenden Aufruf zu erhalten:

    @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
}
65
ShadowMare

Hier ist der tatsächliche Fehler, der mit diesem Problem zusammenhängt http://code.google.com/p/Android-misc-widgets/issues/detail?id=8

Dies besagt im Wesentlichen, dass die onAnimationEnd-Methode nicht wirklich gut funktioniert, wenn ein AnimationListener an eine Animation angehängt ist

Sie können dieses Problem umgehen, indem Sie auf die Animationsereignisse in der Ansicht achten, auf die Sie die Animation auf .__ angewendet haben. Wenn Sie zum Beispiel den Animationslistener an die Animation wie folgt angehängt haben 

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

und dann auf die Animation auf eine ImageView wie folgt anwenden

mImageView.startAnimation(mAnimation);

Um dieses Problem zu umgehen, müssen Sie jetzt eine benutzerdefinierte ImageView erstellen

public class MyImageView extends ImageView {

überschreiben Sie dann die onAnimationEnd-Methode der View-Klasse und stellen Sie die gesamte Funktionalität dort bereit

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

Dies ist die richtige Lösung für dieses Problem. Stellen Sie die Funktionalität in der überschneidungsabhängigen View -> onAnimationEnd-Methode bereit, im Gegensatz zur onAnimationEnd-Methode des AnimationListener, der an die Animation angehängt ist.

Dies funktioniert einwandfrei und gegen Ende der Animation ist kein Flimmern mehr zu hören. Hoffe das hilft.

91
Soham

Ich konnte dieses Problem durch Aufrufen von clearAnimation () in der animierten Ansicht in onAnimationEnd lösen, wodurch das Flimmern wegfiel .__ wurde nur aufgerufen, wenn die Animation bereits beendet ist. Aber ich denke, die Antwort liegt in der Tiefe des Frameworks, wie View/Layout mit dem Callback von Animationen umgeht. Für jetzt nehmen wir es als hackfreie Lösung, das funktioniert einfach.

        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);
32
lucknow_rocks

Ich hatte ein ähnliches Problem und benutzte die Lösung von Soham mit einer benutzerdefinierten Ansichtsklasse.

Es hat gut funktioniert, aber am Ende habe ich eine einfachere Lösung gefunden, die für mich funktioniert hat.

Nach dem Aufruf von view.StartAnimation(animation) und vor dem nächsten Schritt in meinem Programm habe ich eine kurze Verzögerung hinzugefügt, die lang genug ist, um die Animation zu beenden, aber kurz genug, um vom Benutzer nicht bemerkt zu werden: 

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

Ich hatte das gleiche Problem und löste es mit 

view.clearAnimation();

vor

view.startAnimation(anim);
5
savepopulation

Aus irgendeinem Grund funktioniert der OnAnimationStart ordnungsgemäß und der OnAnimationEnd nicht. Also heres, wie ich es ursprünglich gemacht habe und was ich verändert habe:

Versuch 1 (Flimmern): A) Bild von 0px auf 80px verschieben B) Stellen Sie in onAnimationEnd die Position des Bildes auf 80px ein

Versuch 2 (kein Flimmern): A) Legen Sie in onAnimationStart die Position des Bildes auf 80px fest B) Verschieben Sie das Bild von -80px auf 0px

Hoffe das hat Sinn gemacht. Im Grunde habe ich so umgedreht, wie ich es gemacht habe

2
Matt

Versuchen Sie, getAnimation () von Ihrem Objekt zu verwenden:

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
            }
        });
}
1
Butsaty

Wenn Sie die Anzahl der Wiederholungen als unendlich verwenden, wird onAnimationEnd nicht aufgerufen. Überprüfen Sie die Dokumentation link

0
sanjeeb

die Animation kann auch bei Bildschirmdrehung angehalten werden. In diesem Fall wird OnAnimationEnd () nicht aufgerufen. mein Workaround:

 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);
0
Oleg Khalidov

Ich hatte dieses Problem, weil meine Animation nicht im Haupt-Thread gestartet wurde . Dies führte zu einer duration von 0 . Die Animation wurde jedoch korrekt abgespielt - sie rief nur onAnimationEnd() direkt nach der Ausführung.

0

Eine einfache Lösung ist das Hinzufügen einer Zeile zuAnimationListener.onAnimationEnd():

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