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
}
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.
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);
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)
Ich hatte das gleiche Problem und löste es mit
view.clearAnimation();
vor
view.startAnimation(anim);
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
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
}
});
}
Wenn Sie die Anzahl der Wiederholungen als unendlich verwenden, wird onAnimationEnd nicht aufgerufen. Überprüfen Sie die Dokumentation link
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);
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.
Eine einfache Lösung ist das Hinzufügen einer Zeile zuAnimationListener.onAnimationEnd()
:
@Override
public void onAnimationEnd(Animation a) {
a.setAnimationListener(null);
…
}