33

Android ImageViewでアニメーションが終了するまで*待ってからプログラムの実行を続行したいのですが、これを行う適切な方法は何ですか?

  • (このコンテキストでは、「終了」とは、すべてのフレームを1回だけ実行し、最後のフレームで停止することを意味します。このアニメーションがandroid:oneshot = "true"アニメーションになるかどうかは、複数使用するため不明です。何度も実行されますが、継続的ではなく断続的に実行されます)

調査/推測:

A. Android AnimationDrawableはJava.lang.Runnableを実装しているため、私の質問は本質的にJavaスレッドの質問のようです。したがって、おそらくスレッドが解決策です。おそらく答えには参加が含まれますか?

B.他の人のアプローチは、AnimationListenerを使用することだったようです。これは、私の単純なニーズにとっては難しく、不必要に複雑に思えます。それに、どうやってやるのか正確にはわかりません。

C. AnimationDrawableクラスには(ブール値の)isRunningメソッドがあり、これはおそらくwhileループで使用できます(つまり、while(anim.isRunning()){wait(100ms)})。しかし、私はこれが間違ったアプローチであると直感しています。並行性のチュートリアルでも同様のことが言及されているようですが

コードスニペット

   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>

私の質問に対する答えではありませんが、目的の効果を達成するための1つの可能な方法は、次のようなことを行うことによって、さらなるコードの実行を遅らせることです。

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呼び出しでアニメーションを直接実行しました。最後の反復では、スレッドサーフェスビューを使用してアニメーションを実行しています。この最後の方法は、はるかに高速で最良です(この投稿で質問された以外の理由で)。私はそれが誰かを助けることを願っています。

4

4 に答える 4

56

最も簡単な方法は、(遅延した)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スレッドをブロックしようとしないでください(決して、決して、決して!)。そうすると、電話がフリーズし、とにかくアニメーションが表示されなくなります。しばらく待つ必要がある場合は、別のスレッドを使用してください。

于 2011-11-05T01:41:35.043 に答える
47

アニメーションリスナーを使用して、アニメーションライフサイクルフックをリッスンします。

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);
于 2014-01-14T19:47:11.713 に答える
9

あなたを提案する

  • 「アニメーション」の有効期間をカプセル化するオブジェクトを作成します
  • オブジェクトには、スレッドまたはタイマーがあります
  • start()アニメーションにメソッドを提供し、awaitCompletion()
  • フィールドを使用してprivate final Object completionMonitor完了を追跡し、フィールドをsynchronize使用wait()notifyAll()て調整しますawaitCompletion()

コードスニペット:

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

ThreadPoolExecutorまた、単一のスレッドまたはScheduledThreadPoolExecutorでを使用し、アニメーションの各フレームをとしてキャプチャすることもできますCallableCallablesのシーケンスを送信し、invokeAll()またはを使用しCompletionServiceて、アニメーションが完了するまで関心のあるスレッドをブロックします。

于 2011-03-16T05:45:48.103 に答える
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();
于 2015-02-06T09:07:31.343 に答える