Dosssik
3/24/2017 - 12:15 PM

Android recyclerView item animator (bottom to top)

Android recyclerView item animator (bottom to top)

package ru.qasl.cashregister.fragment.boards;

import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SimpleItemAnimator;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;

import java.util.ArrayList;
import java.util.List;

public class BoardsSlidingAnimator extends SimpleItemAnimator {

    private List<RecyclerView.ViewHolder> pendingAdditions = new ArrayList<>();
    private List<RecyclerView.ViewHolder> pendingRemovals = new ArrayList<>();

    @Override
    public void runPendingAnimations() {

        final List<RecyclerView.ViewHolder> additionsTmp = pendingAdditions;
        final List<RecyclerView.ViewHolder> removalsTmp = pendingRemovals;
        pendingAdditions = new ArrayList<>();
        pendingRemovals = new ArrayList<>();

        for (RecyclerView.ViewHolder holderForRemove : removalsTmp) {
            animateRemoveImpl(holderForRemove);
        }
        removalsTmp.clear();

        if (!additionsTmp.isEmpty()) {
            Runnable action = () -> {
                for (RecyclerView.ViewHolder holderForAddition : additionsTmp) {
                    animateAddImpl(holderForAddition);
                }
                additionsTmp.clear();
            };
            // запускаем, когда отработает анимация удаления
            ViewCompat.postOnAnimationDelayed(additionsTmp.get(0).itemView, action, getRemoveDuration());
        }
    }

    @Override
    public boolean animateAdd(RecyclerView.ViewHolder holder) {
        // Прячем и двигаем вьюхи, что бы потом анимировать их появление из этой точки
        pendingAdditions.add(holder);
        holder.itemView.setTranslationY(300);
        holder.itemView.setAlpha(0);
        return true;
    }

    @Override
    public boolean animateRemove(final RecyclerView.ViewHolder holder) {
        pendingRemovals.add(holder);
        return true;
    }

    private void animateAddImpl(final RecyclerView.ViewHolder holder) {
        View view = holder.itemView;
        final ViewPropertyAnimatorCompat animator = ViewCompat.animate(view);

        animator
                .translationY(0)    // иммитируем появление из точки определенной в animateAdd()
                .alpha(1)
                .setDuration(getAddDuration())
                .setInterpolator(new DecelerateInterpolator())
                .setListener(new ViewPropertyAnimatorListener() {
                    @Override
                    public void onAnimationStart(View view) {
                        dispatchAddStarting(holder);
                    }

                    @Override
                    public void onAnimationEnd(View view) {
                        animator.setListener(null);
                        dispatchAddFinished(holder);

                        view.setTranslationY(0);    // clean up
                        view.setAlpha(1);
                    }

                    @Override
                    public void onAnimationCancel(View view) {
                    }
                })
                .start();
    }

    private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {

        View view = holder.itemView;

        final ViewPropertyAnimatorCompat animator = ViewCompat.animate(view);

        animator
                .translationY(-view.getWidth())
                .alpha(0)
                .setDuration(getRemoveDuration())
                .setInterpolator(new AccelerateInterpolator())
                .setListener(new ViewPropertyAnimatorListener() {
                    @Override
                    public void onAnimationStart(View view) {
                        dispatchRemoveStarting(holder);
                    }

                    @Override
                    public void onAnimationEnd(View view) {
                        animator.setListener(null);
                        dispatchRemoveFinished(holder);

                        view.setTranslationY(0);    // cleanup
                        view.setAlpha(1);
                    }

                    @Override
                    public void onAnimationCancel(View view) {
                    }
                }).start();
    }


    @Override
    public boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
        dispatchMoveFinished(holder);   // Можно будет дописать анимацию перемещений столов
        return false;
    }

    @Override
    public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop) {
        if (newHolder != null) {
            dispatchChangeFinished(newHolder, false);
        }
        dispatchChangeFinished(oldHolder, true);
        return false;
    }

    @Override
    public void endAnimation(RecyclerView.ViewHolder item) {
    }

    @Override
    public void endAnimations() {
    }

    @Override
    public boolean isRunning() {
        //Дописать, если нужно будет
        return false;
    }
}