Android-анимация: подождите, пока не закончите? - PullRequest
30 голосов
/ 16 марта 2011

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

  • (в данном контексте «готово» означает, чтоон просматривает все свои кадры ровно один раз и останавливается на последнем. Мне неясно, будет ли эта анимация анимацией android: oneshot = "true", потому что я буду использовать ее несколько раз, но она не будет выполняться непрерывноно периодически)

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

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

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>

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

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 ]

50 голосов
/ 05 ноября 2011

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

41 голосов
/ 14 января 2014

Используйте слушателя Animation для прослушивания хуков жизненного цикла анимации.

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);
9 голосов
/ 16 марта 2011

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

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

2 голосов
/ 06 февраля 2015

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