Подтвердить что ты не робот

Android: как мы можем делать backport withEndAction для более старых версий, с помощью Nine Old Androids

Я работаю над чем-то, что требует около 10 анимаций, которые будут воспроизводиться один за другим, но в конце каждой анимации есть некоторые условия, поэтому я не могу использовать набор анимации или setStartDelay.

Мне было очень легко сделать на желе Bean с новыми методами, из которых сEndAction, пока я делал это как эксперимент, но теперь я должен реализовать его в приложении с minSdk 10.

Я использую Nine Old Android, и он отлично работает, но использование setListner очень сложно и создает код, который трудно поддерживать для 10 последовательных анимаций.

Итак, я думал, создав адаптер, наследующий от девяти старых андроидов, и я мог бы добавить функциюEndAction, которая выполняет runnable?

Может ли кто-нибудь направить меня на то, как это сделать, и есть ли лучший способ сделать это?

Спасибо

4b9b3361

Ответ 1

Я использовал setListener

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        viewPropertyAnimator.setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                doSomething();
            }
        });
    } else {
        viewPropertyAnimator.withEndAction(new Runnable() {
            @Override
            public void run() {
                doSomething();
            }
        });
    }

Ответ 2

Теперь вы можете использовать ViewCompat и добавлять любые анимации, которые вы хотите.

ViewCompat.animate(yourView).scaleY(3).withEndAction(yourRunnable).start();

Ответ 3

Есть два варианта, о которых я могу думать:

  • Создайте свой собственный пул анимации, используя шаблон фасада (это может быть много работы)
  • Получить исходный код из ADT и изменить его. Вот если вы не можете найти его: http://pastebin.com/9nCPC4aR. Скопируйте его (что-то вроде ViewPropertyAnimatorCompat) в свой собственный пакет. Класс, похоже, не имеет большого сцепления с другими элементами Android, поэтому он должен работать так:)
  • UPDATE: вот еще один вариант - очередь анимации. Подобно первой идее, но немного более прямолинейной:

код:

public class AnimationQueue extends LinkedList<Animation> implements
    AnimationListener {

private View mView;

public static AnimationQueue ready(Animation... animations) {
    AnimationQueue queue = new AnimationQueue();
    for (Animation animation : animations) {
        queue.add(animation);
    }
    return queue;
}

public AnimationQueue steady(View view) {
    mView = view;
    return this;
}

public void go() {
    Animation animation = poll();
    animation.setAnimationListener(this);
    mView.startAnimation(animation);
}

@Override public void onAnimationEnd(Animation animation) {
    go();
}

@Override public void onAnimationStart(Animation animation) {
}

@Override public void onAnimationRepeat(Animation animation) {
}

}

Использование:

AnimationQueue.ready(anim1, anim2, anim3).steady(view).go();

Приветствия

Ответ 4

Мое решение Было также использовано фантастическое девяностое сердце.

Вместо of

starsBig[4].animate().rotation(3600).setDuration(2000).withEndAction(runnable)

Я сделал

animate(starsBig[4]).rotationBy(3600).setDuration(2010);
this.runOnUiThread(new Runnable() {
public void run() {
    for (int i = 0; i < 5; i++) {
        starReset(stars[i]);
        starReset(starsBig[i]);
    }
           }
});

Он отлично работал для одной анимации

Ответ 5

Я думаю, у меня есть лучшее решение:

            view.animate().setDuration(2000).alpha(0);
            //timAnimDelay.purge();
            timAnimDelay.schedule(new TimerTask() {
                @Override
                public void run() {

                    // on UI thread
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            // here animation
                        }
                    });
                }
            // delay start
            } , 2000);
            timAnimDelay.purge();

Ответ 6

В принципе, чтобы сделать ваш код более читаемым, вы можете использовать встроенный AnimatorListenerAdapter, чтобы избавить вас от анонимного внутреннего классового беспорядка. Вы можете даже абстрагировать его больше, чтобы он выглядел как withEndAction следующим образом:

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Application;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.view.View;


public class AnimatorActionListener extends AnimatorListenerAdapter {

public enum ActionType {
    START, END;
}

final private ActionType type;
final private Runnable action;

public AnimatorActionListener(Runnable action, ActionType type) {
    this.action = action;
    this.type = type;
}

@Override
public void onAnimationEnd(Animator animation) {
    if (type == ActionType.END) {
        action.run();
    }
}

@Override
public void onAnimationStart(Animator animation) {
    if (type == ActionType.START) {
        action.run();
    }
}
}

И тогда использование будет:

 view.animate()./*...some parameters...*/.setListener(new AnimatorActionListener(new Runnable() {
        @Override
        public void run() {
            // do stuff
        }
    }, ActionType.END)); // or ActionType.START

И для тех, кто должен использовать платформу, встроенную в функции, когда она есть (withStartAction, withEndAction), просто поместите код проверки SDK в AnimatorActionListener тоже, чтобы сохранить класс клиента от беспорядков.