onAnimationEnd没有被调用,onAnimationStart工作正常

时间:2011-03-29 15:23:02

标签: android animation popupwindow

我在PopupWindow中有一个ScrollView。我正在使用TranslateAnimation为ScrollView内容设置动画。

当动画开始时,会调用onAnimationStart侦听器,但不会调用onAnimationEnd。有什么想法吗?

布局:

<?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>

动画代码:

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

更新:我确认调用了onAnimationEnd,但是在延迟一段时间后调用它(假设你在此期间没有启动新动画)。

14 个答案:

答案 0 :(得分:57)

AnimationEnd不可靠。如果您不想使用覆盖OnAnimationEnd的自定义视图重写代码,请使用postDelayed

以下是一些示例代码:

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

虽然看起来很难看,但我可以保证它非常可靠。我将它用于插入新行的ListViews,同时将动画移除到其他行。用AnimationEnd对一个监听器进行压力测试证明是不可靠的。有时AnimationEnd永远不会被触发。您可能希望在动画未完全完成的情况下重新应用postDelayed函数中的任何变换,但这实际上取决于您正在使用的动画类型。

答案 1 :(得分:9)

在我不记得帖子如何阅读以及花了多少时间找到解决此问题的方法后,我发现如果要移动的对象不在屏幕区域上(例如位于屏幕坐标之外)OnAnimationEnd回调没有被召唤。可能是动画在启动后失败(调用start方法,我编写了一个监听器),但没有写入logcat。也许这不是你的情况,但这最终解决了我的问题,并希望它也可以帮助你。

答案 2 :(得分:7)

确保您正在使用 view.startAnimation(Animation) AND NOT view.setAnimation(Animation)。这种简单的混淆可能是一个问题。

答案 3 :(得分:3)

此外,在使用动画时,请不要忘记setFillAfter()true

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

如果fillAfter为true,则此动画执行的转换将在完成后保留。如果未设置,则默认为false。请注意,这在使用AnimationSet链接动画时适用。在AnimationSet本身启动之前不会应用转换。

anim.setFillAfter(true);
mToolbar.startAnimation(anim);

答案 4 :(得分:2)

对于任何绊倒这个问题的人:考虑转而使用Property Animation系统http://developer.android.com/guide/topics/graphics/prop-animation.html

我对在视图上设置淡入/淡出的旧方法(通过AlphaAnimation)有几个问题。 OnAnimationEnd没有被调用等...使用Property Animation所有这些问题都得到了解决。

如果你想支持API&lt; 11设备,Jake Wharton的https://github.com/JakeWharton/NineOldAndroids是可行的方式

答案 5 :(得分:0)

您是否在等待的那个动画之前设置另一个动画?

没有上下文很难理解,如果它是这样的......但它可能是导致它的唯一因素之一。

答案 6 :(得分:0)

我猜它会在一段时间后被调用,因为你正在使用setDuration进行动画并在其中传递1000毫秒。只要通过0,就不会花费一些时间来接听电话。

答案 7 :(得分:0)

延迟可能是由于anim.setDuration(1000)或者如果你在一个线程上这样做,那么可能是由于上下文切换。尝试操纵延迟时间,看看你是否注意到任何差异。

答案 8 :(得分:0)

尝试使用overridePendingAnimation(int,int)。 即 overridePendingAnimation(0,0)

它将覆盖您的默认动画,然后您可以定义自己的动画通过使用View对象调用方法startAnimation。

这是我的示例代码。不知道它对你有帮助。

overridePendingTransition(0,0);
//finish();
v.startAnimation(AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fadeout));
startActivity(new Intent(ContentManagerActivity.this,Mainmenu_activity.class));
overridePendingTransition(R.anim.fadein,0);

答案 9 :(得分:0)

我尝试了你的代码它在OnAnimation start和inAmimationEnd中工作正常,持续时间意味着在完成动画onAnimationEnd之后调用,所以你的代码工作正常

TranslateAnimation anim =new TranslateAnimation(0, 0, -60, 0);
        anim.setDuration(1000);     
        anim.setAnimationListener(new Animation.AnimationListener() {
                public void onAnimationStart(Animation a) {
                    Log.w("Start", "---- animation start listener called"  );
                }
                public void onAnimationRepeat(Animation a) {}
                public void onAnimationEnd(Animation a) {
                    Log.d(" end  ","---- animation end listener called"  );
                }
            });
            mIv.setAnimation(anim);
            mIv.startAnimation(anim);

答案 10 :(得分:0)

可能有人仍然遇到此问题并且没有找到解决方案 - 尽管读取了很多stackoverflow答案 - 就像我一样!

所以我的情况是:我使用了animatorSet

  1. 我没有一个可以调用clearAnimation的视图,
  2. 我没有从backgroundThread调用我的动画 - 你永远不应该这样做,btw-
  3. 作为解决方案,我确实在animatorSet.end()

    之前致电animatorSet.start()

答案 11 :(得分:0)

当您在部分屏幕外的视图中启动动画命令时,将调用动画开始和onStartListener,但动画不会完全运行(不知何故它在中间被中断)。我的猜测是,由于视图在屏幕外,它被取消,因此它的onFinish没有被调用。作为一种解决方法,我创建了自己的动画侦听器,它启动了一个处理程序,并使用postDelayed通知用户动画结束事件。在科特林:

abstract class PartiallyOffScreenAnimationListener : Animation.AnimationListener, AnimationListener {
    override fun onAnimationRepeat(animation: Animation?) {
        onAnimationRepeat_(animation)
    }
    override fun onAnimationEnd(animation: Animation) {}

    override fun onAnimationStart(animation: Animation) {
        onAnimationStart_(animation)
        Handler().postDelayed({
            onAnimationEnd_(animation)
            animation.setAnimationListener(null)
        }, animation.duration + 50)
    }
}

请注意,在动画未完全运行的情况下,视图可能会处于不一致状态(例如,动画布局参数可能会导致奇怪的中间插值因子被丢弃。因此,您应该在最后回调验证视图是否处于所需状态。如果没有,只需手动设置它。

答案 12 :(得分:0)

像下面这样做

  1. 制作动画最终
  2. 在处理程序
  3. 中调用它
  4. 应该实例化一次侦听器。
  5. 清除动画。
  6. 例如,

    view.clearAnimation();

    new Hander().post(
       run() {
    final TranslateAnimation ani = new TranslateAnimation(0, 0, 0, 0);
    ani.setAnimationListener(mListener);
     }
    );
    
    private Animation.AnimationListener mListener = new Animation.AnimationListener() {
    }
    

答案 13 :(得分:-1)

你在哪里开始动画?如果在onCreate中,那就错了。尝试在onResume中进行。