android动画未在onAnimationEnd中完成


67

onAnimationEnd尽管将事件animation.hasEnded设置为true,但似乎在触发事件时并未真正完成android动画。

我希望我的视图在其结束时更改其背景可绘制的背景ScaleAnimation,但是您可以清楚地看到它在完成前几毫秒就被更改了。问题在于,它闪烁是因为新背景在短时间内缩放了,直到动画真正完成为止。

是否有办法获得动画的真实结尾,或者只是防止在短时间内缩放新背景?

谢谢!


//编辑:我正在使用AnimationListener来获取以下调用:

    @Override
public void onAnimationEnd(Animation animation)
{
    View view = (MyView) ((ExtendedScaleAnimation) animation).getView();

    view.clearAnimation();
    view.requestLayout();
    view.refreshBackground(); // <-- this is where the background gets changed
}

1
您是否正在使用AnimationListener来获取OnAnimationEnd调用或其他方式?您可以从您的项目中发布相关的代码,以便我们更好地了解发生了什么吗?
FoamyGuy 2011年

好的,谢谢!我正在编辑问题以添加代码和一些细节。
ShadowMare

你能帮我ShadowMare,我有同样的问题,不知道如何解决这个
米洛什

您是否尝试过使用下面提供的代码?这对我行得通。它基本上可以让视图处理onAnimationEnd而不是动画本身。让我知道您是否需要更多帮助。
ShadowMare 2012年

@ShadowMare大家好,您能帮我解决这个问题,因为我有类似的问题。
米洛什2012年

Answers:


93

这是与此问题相关的实际错误http://code.google.com/p/android-misc-widgets/issues/detail?id=8

这基本上表明当将AnimationListener附加到Animation时,onAnimationEnd方法实际上不能很好地工作

解决方法是在将动画应用到的视图中侦听动画事件,例如,如果最初将动画侦听器附加到这样的动画上,

mAnimation.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationEnd(Animation arg0) {
        //Functionality here
    }
});

然后像这样将动画应用于ImageView

mImageView.startAnimation(mAnimation);

要变通解决此问题,您现在必须创建一个自定义ImageView

public class MyImageView extends ImageView {

然后覆盖onAnimationEndView类的方法,并在那里提供所有功能

@Override
protected void onAnimationEnd() {
    super.onAnimationEnd();
    //Functionality here
}

这是解决此问题的正确方法,请在重写的View-> onAnimationEnd方法中提供功能,而不是附加到Animation的AnimationListener的onAnimationEnd方法。

这可以正常工作,并且在动画结束时不再闪烁。希望这可以帮助。


没问题,很高兴我能帮助您:)
Soham

Soham,我有同样的问题,不知道如何解决。
米洛什

2
是的,确实是,我正在将动画添加到imageView上。我创建了视图类,但我从来没有进入onAnimationEnd
米洛什

2
以及如何使用内容视图布局?在这种情况下,不能使用嵌套类,因此不能使用父类功能。
Konstantin Konopko 2014年

3
我们再也无法在该链接上查看该错误了,但这仍然是Android M,N中的问题...
androidguy

32

我正在通过在onAnimationEnd内被动画化的视图上调用clearAnimation()来解决此问题,这消除了闪烁的原因,为什么有人必须这样做,因为仅当动画已经结束时才应调用onAnimationEnd回调。但是我想答案就在于Framework的深度,即视图/布局如何处理动画回调。现在,将其作为无黑客解决方案,就可以了。

        animation.setAnimationListener(new AnimationListener() {

        public void onAnimationEnd(Animation anim) {
            innerView.clearAnimation();   // to get rid of flicker at end of animation

            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams
            (innerBlockContainer.getWidth(), innerBlockContainer.getHeight());

            /* Update lp margin, left/top to update layout after end of Translation */
            ViewGroup parent_ofInnerView = (ViewGroup)innerView.getParent();
            vp.updateViewLayout(innerBlockContainer, lp);

        }

        public void onAnimationRepeat(Animation arg0) {}

        public void onAnimationStart(Animation arg0) {
        }

    });

     innerView.startAnimation(animation);

1
在我看来,这没有帮助。但是,Soham的建议确实做到了。
克里斯·范·贝尔

1
哇!简单的单线解决方案,就像一个魅力!我刚刚添加了“ view.clearAnimation();” 在我的“ view.layout()”之前-瞧!:-)
Brad

我几乎爱你,男人!在看了5个小时的代码后,想自杀;)您救了我的命!
sennin 2012年

5
尽管调用clearAnimation()将再次调用onAnimationEnd
Leeeeeeelo

救了我!干杯
Thijs Limmen 2014年

6

我有一个类似的问题,我在自定义视图类中使用了Soham的解决方案。

效果很好,但是最后,我找到了一个对我有用的简单解决方案。

在调用之后view.StartAnimation(animation),在程序的下一步之前,我添加了一个短暂的延迟,该延迟足够长以使动画结束,但又足够短以使用户无法注意到:

new Handler().postDelayed(new Runnable() {
       @Override
       public void run() {
           nextStepInMyProgram();
       }
     }, 200);// delay in milliseconds (200)

2
可怕的解决方案,但没有覆盖类的作品,也仅适用于post(Runnable),没有postDelayed(Runnable,int)
Massimo

Massimo-post(Runnable)不允许动画完成,因此Doigen是正确的postDelayed(Runnable)。只需稍作修改,我们就可以使用delay =“ animation.getDuration()”
Ankit Bansal 2014年

这与AnimatorSet一起在onAnimationStart中设置功能起作用
ElYeante 2014年

除了可怕之外,此解决方案还不完整:不能涵盖所有情况。如果您在nextStepInMyProgram()之后触发了更多动画,则会产生副作用
boctulus'Aug

6

我有同样的问题,并使用解决了

view.clearAnimation();

之前

view.startAnimation(anim);

调用view.invalidate(); 设置动画后,它对我
有用

2

由于某种原因,onAnimationStart可以正常工作,而onAnimationEnd无法正常工作。因此,这是我最初的做法以及所做的更改:

尝试1(闪烁):a)将图片从0px移动到80px b)在onAnimationEnd中,将图片的位置设置为80px

尝试2(无闪烁):a)在onAnimationStart中,将图像的位置设置为80px b)将图像从-80px移至0px

希望有道理。基本上我改变了做事的方式


使用翻译动画会更好。
丹尼尔·本尼迪克

2

尝试从您的对象中使用getAnimation():

public void onShowListBtnClick(View view)
    {
        rightPanel.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.slide_left));

        rightPanel.getAnimation().setAnimationListener(new Animation.AnimationListener() {    
            @Override
            public void onAnimationStart(Animation animation) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                // write your code here
            }
        });
}

1

动画也可以在屏幕旋转时停止。在这种情况下,不会调用onAnimationEnd()。我的解决方法:

 animation.setDuration(animationDuration);
 animation.setAnimationListener(new AnimationListenerAdapter() {...});
 view.startAnimation(animation);
 handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(!animation.hasEnded()) {
                    // here you can handle this case
                }
            }
        }, animationDuration + 100);

0

一个简单的解决方法是在AnimationListener.onAnimationEnd()

@Override 
public void onAnimationEnd(Animation a) {
    a.setAnimationListener(null);
    …
}

0

我遇到了这个问题,因为我Animation没有在主线程中启动。结果duration为0。但是,Animation确实可以正常播放-onAnimationEnd()执行后立即调用了它。


0

如果将重复计数用作无限,则不会调用onAnimationEnd。检查文档链接


0

您也可以使用setUpdateListener,然后检查动画进度的当前部分并采取相应措施。

以下是淡出动画的Kotlin示例,该示例最终使视图脱离了布局:

view.animate()
        .alpha(0f)
        .setDuration(duration)
        .setUpdateListener { animation ->
            if (animation.animatedFraction > 0.99f) {
                view.visibility = View.GONE
            }
        }
        .start()

-1

这对我有用:

@Override
public void onAnimationUpdate(ValueAnimator animation) {
    if (Float.compare(animation.getAnimatedFraction(),1.0f)) {
    // animation ended;
        //do stuff post animation
    }
}

1
这也可能会发生不止一次,尤其是持续时间足够长时。
Alex Cohn 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.