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

问题描述 投票:43回答:14

我在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被调用但是在一段延迟后被调用(假设您在此期间没有启动新动画)。

android animation popupwindow
14个回答
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函数中的任何变换,但这实际上取决于您正在使用的动画类型。


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

0
投票

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

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

  1. 没有一个我可以称之为clearAnimation的视图,
  2. 我没有从backgroundThread调用我的动画 - 你永远不应该这样做,顺便说一句

作为解决方案,我确实在animatorSet.end()之前打电话给animatorSet.start()


0
投票

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

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

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


0
投票

像下面这样做

  1. 让动画决赛
  2. 在处理程序内调用它
  3. 应该实例化一次监听器。
  4. 清晰的动画。

例如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() {
}

-1
投票

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


9
投票

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


7
投票

确保你使用的是view.startAnimation(Animation)而不是view.setAnimation(Animation)。这种简单的混淆可能是一个问题。


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

2
投票

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

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

如果你想支持API <11设备,Jake Wharton的https://github.com/JakeWharton/NineOldAndroids是要走的路


0
投票

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

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


0
投票

我想它会在一段时间后被调用,因为你正在使用动画的持续时间设置并在其中传递1000毫秒。只需传递0,就不需要花费一段时间才能被调用。


0
投票

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


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);
© www.soinside.com 2019 - 2024. All rights reserved.