【问题标题】:Android Animation: Wait until finished?Android动画:等到完成?
【发布时间】:2011-07-16 08:01:02
【问题描述】:

我想等到 Android ImageView 中的动画完成*后再继续执行程序,这样做的正确方法是什么?

  • (在这种情况下,“完成”意味着它恰好运行一次所有帧并在最后一个停止。我不清楚这个动画是否会是一个 android:oneshot="true" 动画,因为我会多次使用它,但它不会连续运行而是间歇性运行)

研究/猜测:

A.从本质上讲,我的问题似乎是一个 Java 线程问题,因为 Android AnimationDrawable 实现了 Java.lang.Runnable。所以也许线程是解决方案。也许答案将包括join

B.其他人的方法似乎是使用AnimationListener,这对于我的简单需求来说似乎很困难而且不必要地复杂。另外,我不确定该怎么做。

C. AnimationDrawable 类有一个 (boolean) isRunning 方法,它可能会在 while 循环中使用(即 while(anim.isRunning()){wait(100ms)})。但我有一种直觉,这是错误的方法。虽然concurrency tutorial中似乎提到了类似的东西

代码片段

   this.q_pic_view.setImageResource(0);
    this.q_pic_view.setBackgroundResource(R.drawable.animation_test);
    AnimationDrawable correct_animation = (AnimationDrawable) this.q_pic_view.getBackground();
    correct_animation.start();

    //here I tried to implement option C but it didn't work
    while(correct_animation.isRunning()){
        try {
           Thread.sleep(20);
        } catch (InterruptedException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
        }
    }

动画

<?xml version="1.0" encoding="utf-8"?>
<animation-list android:id="@+id/AnimTest" android:oneshot="true" xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:drawable="@drawable/animtest001" android:duration="33"/>
  <item android:drawable="@drawable/animtest002" android:duration="100"/>
  <item android:drawable="@drawable/animtest003" android:duration="66"/>
  <item android:drawable="@drawable/animtest004" android:duration="66"/>
  <item android:drawable="@drawable/animtest005" android:duration="33"/>
  <item android:drawable="@drawable/animtest006" android:duration="66"/>
  <item android:drawable="@drawable/animtest007" android:duration="33"/>
  <item android:drawable="@drawable/animtest008" android:duration="66"/>
  <item android:drawable="@drawable/animtest009" android:duration="100"/>
  <item android:drawable="@drawable/animtest010" android:duration="100"/>
</animation-list>

实现预期效果的一种可能方法是通过执行以下操作来延迟进一步代码的执行,尽管这不是我的问题的答案:

int duration = 0;
//Add all of the frames together
for (int i=0; i<my_animation.getNumberOfFrames(); i++){
    duration = duration + correct_animation.getDuration(i);
    }
//delay the execution 
Handler handler = new Handler();
handler.postDelayed(new Runnable(){
    public void run() {
       DoYourNextStuff();
        }
}, duration); //delay is here

编辑:有很多方法可以解决这个问题,给出的答案可能确实解决了问题我没有测试它,但我最终只是等待了正确的时间(起初),然后我改为使用异步任务(它有一个完成的处理程序方法)并直接在异步任务的 updateProgress 调用中运行我的动画。在最后一次迭代中,我使用线程表面视图来运行动画。最后一种方法是迄今为止最快和最好的(出于本文中所问的其他原因)。我希望它可以帮助某人。

【问题讨论】:

  • 动画完成需要多长时间..?
  • CapDroid 如果您将上述 xml sn-p 中的所有整数相加,您将获得动画的总持续时间。但我正在寻找一个通用的解决方案,因此在这种情况下对我没有帮助。
  • 试试这个 Thread.sleep(663); 663 = 动画总时间..

标签: java android concurrency android-animation


【解决方案1】:

最简单的方法是将(延迟的)Runnable 发布到 UI 线程:

Animation fadeout = new AlphaAnimation(1.f, 0.f);
fadeout.setDuration(500);
view.startAnimation(fadeout);
view.postDelayed(new Runnable() {
    @Override
    public void run() {
        view.setVisibility(View.GONE);
    }
}, 500);

这样可以轻松完成这项工作。并且从不(从不,从不,从不!)尝试阻塞 Android 中的 UI 线程。如果你这样做了,手机就会死机,无论如何你都看不到动画。 如果您需要等待一段时间,请使用另一个线程。

【讨论】:

  • 很好的答案,虽然我在 run() 中执行繁重的/数据库工作时遇到了一个小问题,以及动画是否结束的条件。 animation.hasEnded() 它可能不会一直返回 true。增加postDelayed中的延迟毫秒数比动画持续时间,解决了这个问题:)
  • 这段代码太棒了,太小了,就像一个魅力!感谢发帖!!
  • 我真的不相信这是一个好的解决方案。硬编码值很少是。
【解决方案2】:

使用动画监听器来监听动画生命周期钩子。

Animation fadeout = new AlphaAnimation(1.f, 0.f);
fadeout.setDuration(500);    
final View viewToAnimate = view;
fadeout.setAnimationListener(new AnimationListener(){

   @Override
   public void onAnimationStart(Animation animation){}

   @Override
   public void onAnimationRepeat(Animation animation){}

   @Override
   public void onAnimationEnd(Animation animation){
       viewToAnimate.setVisibility(View.GONE);
   }
});
view.startAnimation(fadeout);

【讨论】:

  • 我不知道这不是公认的最受好评的答案。这显然是正确的。无论如何,我要 +1。
  • @katzenhut 因为在当前上下文中答案是错误的。 OP 使用的 AnimationDrawable 甚至不是从动画派生的。因此,如果您使用的是从 Animation 类派生的动画,则此答案是正确的,但对于 AnimationDrawable 则不正确。 AnimationDrawable 在其生命周期方面没有像 Animation 类那样的回调。
  • @Zainodis - android 中奇怪的命名转换从未停止让我感到惊讶......但你是对的。感谢您的澄清!
【解决方案3】:

建议你

  • 创建一个对象来封装“动画”生命周期
  • 在对象中,您将拥有一个线程或一个计时器
  • start()动画和awaitCompletion()提供方法
  • 使用private final Object completionMonitor 字段来跟踪完成情况,在上面使用synchronize,并使用wait()notifyAll() 来协调awaitCompletion()

代码sn-p:

final class Animation {

    final Thread animator;

    public Animation()
    {
      animator = new Thread(new Runnable() {
        // logic to make animation happen
       });

    }

    public void startAnimation()
    {
      animator.start();
    }

    public void awaitCompletion() throws InterruptedException
    {
      animator.join();
    }
}

您也可以使用带有单线程的ThreadPoolExecutorScheduledThreadPoolExecutor,并将动画的每一帧捕获为Callable。提交Callables 序列并使用invokeAll()CompletionService 阻止您感兴趣的线程,直到动画完成。

【讨论】:

    【解决方案4】:

    您好,另一种选择是使用ObjectAnimator。再次正如其他人提到的那样,您将不得不使用 Listner

    //get an image resource    
    ImageView imgView = (ImageView) findViewById(R.id.some_image);      
    //create and init an ObjectAnimator  
    ObjectAnimator animation;
    animation = ObjectAnimator.ofFloat(imgView, "rotationY", 0.0f, 360f);
    
    //set the duration of each iteration
    animation.setDuration(1500);
    //set number of iterations
    animation.setRepeatCount(1);
    //set setInterpolator 
    
    animation.setInterpolator(new AccelerateDecelerateInterpolator());
    //Add a listner to check when the animation ends
    animation.addListener(new AnimatorListenerAdapter() {
           @Override
           public void onAnimationEnd(Animator animation) {
                    //postFirstAnimation(): This function is called after the animation ends
                    postFirstAnimation();
           }
    });
    //start the animation
    animation.start();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-17
      • 2013-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 2015-10-03
      相关资源
      最近更新 更多