52

我在 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 已被调用,但它是在一些延迟后调用的(前提是您在那段时间没有启动新动画)。

4

15 回答 15

62

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函数中的任何转换,但这实际上取决于您使用的动画类型。

于 2012-12-14T14:54:19.517 回答
10

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

于 2013-01-19T13:28:56.040 回答
10

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

于 2015-03-13T02:55:59.873 回答
3

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

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

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

anim.setFillAfter(true);
mToolbar.startAnimation(anim);
于 2011-06-17T12:51:59.660 回答
2

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

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

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

于 2014-10-26T16:30:11.007 回答
0

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

于 2011-08-29T06:21:59.273 回答
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);
于 2011-09-08T07:39:42.760 回答
0

像下面那样做

  1. 使动画最终
  2. 在处理程序中调用它
  3. listener 应该被实例化一次。
  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() {
}
于 2017-07-27T14:00:15.340 回答
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)
    }
}

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

于 2017-02-10T10:09:59.713 回答
0

在其他答案中未描述的情况下发生在我身上。试过这个,它没有工作:

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()
}
于 2021-12-30T11:21:49.400 回答
0

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

所以我的情况是:我使用animatorSet并且

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

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

于 2016-03-31T06:46:18.823 回答
-1

我尝试了您的代码,它在 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);
于 2011-09-15T04:18:16.210 回答
-1

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

于 2011-04-07T08:56:24.003 回答
-1

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

于 2011-06-27T14:09:41.840 回答
-1

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

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

于 2011-04-06T15:25:49.543 回答