Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onAnimationEnd is not getting called, onAnimationStart works fine

I've a ScrollView in the PopupWindow. I'm animating ScrollView contents using TranslateAnimation.

When animation starts, the onAnimationStart listener is called but the onAnimationEnd is not getting called. Any ideas ?

Layout :

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:background="@drawable/popup_window_bg"
   android:layout_width="match_parent"
   android:layout_height="wrap_content">
  <View
     android:layout_width="@dimen/toolbar_padding_left"
     android:layout_height="@dimen/toolbar_height"/>
  <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+web/toolbar"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:scrollbars="none"
     android:visibility="invisible">
    <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:orientation="vertical">

       ...

    </LinearLayout>
  </ScrollView>
</LinearLayout>

Animation code :

mToolbar = mPopupContents.findViewById( R.web.toolbar );
TranslateAnimation anim =
    new TranslateAnimation(0, 0, -60, 0);
anim.setDuration(1000);
anim.setAnimationListener(new Animation.AnimationListener() {
        public void onAnimationStart(Animation a) {
            Log.d(LOGTAG, "---- animation start listener called"  );
        }
        public void onAnimationRepeat(Animation a) {}
        public void onAnimationEnd(Animation a) {
            Log.d(LOGTAG, "---- animation end listener called"  );
        }
    });
mToolbar.startAnimation(anim);

Update : I verified that the onAnimationEnd is called but it is called after some delay (provided you don't start the new animation during that time).

like image 608
Karan Avatar asked Mar 29 '11 15:03

Karan


4 Answers

AnimationEnd is not reliable. If you don't want to rewrite your code with custom views that override OnAnimationEnd, use postDelayed.

Here's some example code:

final FadeUpAnimation anim = new FadeUpAnimation(v);
anim.setInterpolator(new AccelerateInterpolator());
anim.setDuration(1000);
anim.setFillAfter(true);
new Handler().postDelayed(new Runnable() {
    public void run() {
        v.clearAnimation();
        //Extra work goes here
    }
}, anim.getDuration());
v.startAnimation(anim);

While it MAY seem ugly, I can guarantee it's very reliable. I use it for ListViews that are inserting new rows while removing with animation to other rows. Stress testing a listener with AnimationEnd proved unreliable. Sometimes AnimationEnd was never triggered. You might want to reapply any transformation in the postDelayed function in case the animation didn't fully finish, but that really depends on what type of animation you're using.

like image 200
ShortFuse Avatar answered Sep 24 '22 05:09

ShortFuse


After I don't remember how may posts read and days spent finding out a solution for this issue I discovered that if the object to move is not on the Screen region (for example is positioned out of the screen coords) OnAnimationEnd callback is not getting called. Probably the animation fails just after started (start method is called, I coded a listener) but nothing is wrote into logcat. Maybe this is not exactly your case but this finally solved my problem and hope it can help you too.

like image 43
Lisitso Avatar answered Sep 20 '22 05:09

Lisitso


Make sure that you are USING view.startAnimation(Animation) AND NOT view.setAnimation(Animation). This simple confusion may be a problem.

like image 12
ralphgabb Avatar answered Sep 21 '22 05:09

ralphgabb


Also, when using animations, don't forget the setFillAfter() to true.

http://developer.android.com/reference/android/view/animation/Animation.html#setFillAfter(boolean)

If fillAfter is true, the transformation that this animation performed will persist when it is finished. Defaults to false if not set. Note that this applies when using an AnimationSet to chain animations. The transformation is not applied before the AnimationSet itself starts.

anim.setFillAfter(true);
mToolbar.startAnimation(anim);
like image 3
Entreco Avatar answered Sep 24 '22 05:09

Entreco