Android Animation: Подождите, пока не закончите?

Я хотел бы подождать, пока анимация закончится * в Android ImageView до продолжения выполнения программы, каков правильный способ сделать это?

  • (В этом контексте «законченный» означает, что он проходит через все свои кадры ровно один раз и останавливается на последнем. Я не понимаю, будет ли эта анимация андроидом: oneshot = «true», потому что я буду использовать ее несколько Раз, но он не будет работать непрерывно, но с перерывами)

Исследования / Догадки:

A. В глубине души мой вопрос, кажется, является вопросом Java-потока, потому что Android AnimationDrawable реализует Java.lang.Runnable . Таким образом, потоки могут быть решением. Возможно, ответ будет включать в себя присоединение ?

B. Подход других, похоже, заключался в использовании AnimationListener , это кажется сложным и излишне сложным для моих простых потребностей. Плюс я точно не знаю, как это сделать.

C. Класс AnimationDrawable имеет (boolean) метод 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> 

Один из возможных способов достижения желаемого эффекта, хотя и не ответ на мой вопрос, заключается в том, чтобы отложить выполнение дополнительного кода, выполнив что-то вроде этого:

 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 

Edit: Есть много способов решить эту проблему, ответ, возможно, решает проблему, которую я не тестировал , но в итоге я просто ожидал нужного количества времени (сначала), затем я перешел на использование задачи async (Который имеет метод обработчика для завершения) и запускал мою анимацию в вызове updateProgress задачи async напрямую. В последней итерации я использую резьбовое представление поверхности для запуска анимации. Этот последний путь, безусловно, самый быстрый и лучший (по другим причинам, о которых спрашивали в этом посте). Надеюсь, это поможет кому-то.

Solutions Collecting From Web of "Android Animation: Подождите, пока не закончите?"

Предложить вам

  • Создайте объект для инкапсуляции времени анимации
  • В объекте у вас будет поток или таймер
  • Предоставьте методы для start() анимации и awaitCompletion()
  • Используйте private final Object completionMonitor поле notifyAll() 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 и захватывать каждый кадр анимации как Callable . Передача последовательности Callable s и использование invokeAll() или CompletionService для блокировки вашего интересующего потока до завершения анимации.

Самый простой способ – отправить (отложенное) Runnable в поток пользовательского интерфейса:

 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. Если вы это сделаете, телефон замерзает, и вы все равно не увидите анимацию. Если вам нужно подождать некоторое время, используйте другой поток.

Используйте прослушиватель анимации, чтобы прослушивать крючки жизненного цикла анимации.

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

Привет, другие альтернативы используют 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();