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