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

Posted

技术标签:

【中文标题】onAnimationEnd 没有被调用,onAnimationStart 工作正常【英文标题】:onAnimationEnd is not getting called, onAnimationStart works fine 【发布时间】:2011-07-25 09:35:15 【问题描述】:

我在 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_
   android:layout_>
  <View
     android:layout_
     android:layout_/>
  <ScrollView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+web/toolbar"
     android:layout_
     android:layout_
     android:scrollbars="none"
     android:visibility="invisible">
    <LinearLayout
       android:layout_
       android:layout_
       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 已被调用,但它在延迟一段时间后被调用(前提是您在此期间没有启动新动画)。

【问题讨论】:

@Viktor 我已经更新了问题。 你能测试一下在 XML 文件中定义它,看看它是否在那里工作吗? 查看了 API,它告诉我:通知动画结束。对于重复计数设置为 INFINITE 的动画,不会调用此回调。 已经尝试在 xml 中定义这个(没有设置监听器,因为我不知道该怎么做),但没有运气:( 尝试“adb logcat -v time”显示调用onAnimationStart和onAnimationEnd的时间。你能根据上面的代码粘贴一些结果吗?谢谢 【参考方案1】:

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 函数中重新应用任何转换,以防动画未完全完成,但这实际上取决于您使用的动画类型。

【讨论】:

非常感谢@ShortFuse。我正在努力在onAnimationStart() 中将视图的可见性设置为View.VISIBLE,这对于某些android 版本不起作用。阅读您的答案后,我得出了以下结论:workThatWouldGoInOnAnimationStart();view.postDelayed(workThatWouldGoInOnAnimationEnd(), anim.getDuration());view.startAnimation(anim);【参考方案2】:

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

另外,在使用动画时,不要忘记 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);

【讨论】:

【参考方案5】:

对于遇到此问题的任何人:考虑改用属性动画系统 http://developer.android.com/guide/topics/graphics/prop-animation.html

我在使用旧的动画淡入/淡出动画方式(通过 AlphaAnimation)时遇到了几个问题。 OnAnimationEnd 没有被调用等等......使用属性动画所有这些问题都得到了解决。

如果您想支持 APIhttps://github.com/JakeWharton/NineOldAndroids 是您的最佳选择

【讨论】:

【参考方案6】:

延迟可能是由于 anim.setDuration(1000) 或者如果您在线程上执行此操作,则可能是由于上下文切换。尝试操纵延迟时间,看看您是否注意到任何差异。

【讨论】:

【参考方案7】:

尝试使用 overridePendingAnimation(int,int)。 IE。 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);

【讨论】:

【参考方案8】:

可能有人仍然遇到这个问题并且没有找到解决方案 - 即使阅读了很多 *** 答案 - 就像我一样!

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

    没有一个视图可以调用 clearAnimation, 我没有从 backgroundThread 调用我的动画 - 你不应该那样做,顺便说一句 -

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

【讨论】:

【参考方案9】:

当您在部分屏幕外的视图中启动动画命令时,动画开始并调用 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)
    

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

【讨论】:

如果我们使用这个监听器并且动画正常结束会发生什么。我会收到两个 onAnimationEnd 回调吗?【参考方案10】:

像下面那样做

    最终制作动画 在处理程序中调用它 监听器应该被实例化一次。 清晰的动画。

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

【讨论】:

【参考方案11】:

在其他答案中未描述的情况下发生在我身上。试过了,还是不行:

ValueAnimator.ofInt(currentHeight, desiredHeight).apply 
     duration = 500
     addListener  
         doOnEnd 
             Log.d(TAG, "animate: animation ended")
         
     
     start()

更改为此解决了问题。可惜不知道为什么。

ValueAnimator.ofInt(currentHeight, desiredHeight).apply 
     duration = 500
     doOnEnd 
           Log.d(TAG, "animate: animation ended")
     
      start()

【讨论】:

【参考方案12】:

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

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

【讨论】:

没有。我没有设置任何其他动画。我也有一个变量来控制它。【参考方案13】:

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

【讨论】:

它不在onCreate中,在用户交互后调用。【参考方案14】:

我猜它会在某个时间后被调用,因为您正在使用 setDuration 进行动画并在其中传递 1000 毫秒。只需传递 0,就不会需要一段时间才能被调用。

【讨论】:

【参考方案15】:

我试过你的代码,它在 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);

【讨论】:

以上是关于onAnimationEnd 没有被调用,onAnimationStart 工作正常的主要内容,如果未能解决你的问题,请参考以下文章

Android动画onAnimationEnd会被调用两次

Android 在动画结束回调onAnimationEnd()中remove view的崩溃解决方法及源码分析

方法 View.clearAnimation 和 Animation.AnimationListener.onAnimationEnd 有啥关系?

如何避免 Animator 动画的加速/减速?

您可以使用更多参数构建 Xamarin UITest 查询吗?

如何以最小的影响重新启动 CSS 动画