In-Out анимация в Android

в 10:39, , рубрики: android, ics, баги, Разработка под android, метки: , ,

Недавно мне понадобилось создать несложную циклическую in-out анимацию вида в Android. Казалось бы, что может быть проще, учитывая, что в Android есть замечательный класс Animation. Однако, он не позволяет создать такой тип анимации без написания дополнительного кода, и, более того, костылей.
Под катом вы можете увидеть, как же это все же реализовать.

Хотелось бы заранее заметить, что речь идет об ICS, однако, указанный ниже баг присутствовал и в Honeycomb, и был любезно перетащен говнокоразработчиками из Google в четвертую ветку.

Итак, я решил использовать класс AnimationSet, который позволяет задать несколько анимаций, идущих друг за другом. В топике на замечательном ресурсе Stackoverflow был приведен хороший пример использования этого класса:

Animation fadeIn = new AlphaAnimation(0, 1);
fadeIn.setInterpolator(new DecelerateInterpolator());
fadeIn.setDuration(1000);
Animation fadeOut = new AlphaAnimation(1, 0);
fadeOut.setInterpolator(new AccelerateInterpolator());
fadeOut.setStartOffset(1000);
fadeOut.setDuration(1000);
AnimationSet animation = new AnimationSet(false);
animation.addAnimation(fadeIn);
animation.addAnimation(fadeOut);
this.setAnimation(animation);

В этом коде используется анимация для альфа-канала вида, но нас это мало волнует, мы можем просто заменить его на RotateAnimation. Вроде бы все, проблема решена — а вот фиг — не работает! Вид то вообще не двигается, то поворачивается в одну сторону и замирает.

В результате мучений я решил написать свой костыль:

public class TogglesAnimator implements AnimationListener {
    private static final String TAG = "TogglesAnimator";

    // Текущая анимация. Сначала идет In
    private int mCurrentAnimation = 0;
    private View mView;

    private RotateAnimation mInAnimation;
    private RotateAnimation mOutAnimation;

    public TogglesAnimator(View view, float degree, long duration) {
        mView = view;
        int pivotX = mView.getWidth() / 2;
        int pivotY = mView.getHeight() / 2;
        Log.d(TAG, "Pivots: " + pivotX + ", " + pivotY);

        // Поворачиваем вид от -degree до degree градусов
        mInAnimation = new RotateAnimation(-degree, degree, pivotX, pivotY);
        // За duration миллисекунд
        mInAnimation.setDuration(duration);
        // И обратно
        mOutAnimation = new RotateAnimation(degree, -degree, pivotX, pivotY);
        mOutAnimation.setDuration(duration);

        mInAnimation.setAnimationListener(this);
        mOutAnimation.setAnimationListener(this);
        mView.startAnimation(mInAnimation);
    }
    /**
     * Create animation for the given view
     *
     * <hh user=param> view
     *            view to create the animation
     * <hh user=return> created animator instance
     */
    public static TogglesAnimator createAnimation(View view, float degree,
            long duration) {
        TogglesAnimator animator = new TogglesAnimator(view, degree, duration);
        return animator;
    }
    /**
     * Animation was ended
     */
    @Override
    public void onAnimationEnd(Animation animation) {
        mView.clearAnimation();

        // Если закончившаяся анимация - In, то запускаем Out
        if (mCurrentAnimation == 0) {
            mCurrentAnimation = 1;
            mView.startAnimation(mOutAnimation);

        // Ну и наоборот
        } else if (mCurrentAnimation == 1) {
            mCurrentAnimation = 0;
            mView.startAnimation(mInAnimation);
        }
    }

    @Override
    public void onAnimationRepeat(Animation animation) {
        // TODO Auto-generated method stub
    }
    @Override
    public void onAnimationStart(Animation animation) {
        // TODO Auto-generated method stub
    }
}

Собственно, все. Использовать этот класс очень просто:

TogglesAnimator.createAnimation(view, 5, 400);

Естественно, анимацию можно заменить на любую другую. В моем случае вид будет циклически поварачиваться от -degree до degree градусов и обратно.

Спасибо за внимание, надеюсь, кому-нибудь этот пост будет полезен.

Автор: RankoR

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js