动画使用
// 自定义ItemView的动画时间
DefaultItemAnimator itemAnimator = new DefaultItemAnimator();
//也可以不设置时间,使用默认时间
itemAnimator.setAddDuration(1000);
itemAnimator.setRemoveDuration(1000);
itemAnimator.setChangeDuration(1000);
itemAnimator.setMoveDuration(1000);
recyclerView.setItemAnimator(itemAnimator);
动画调用
我们在平时更新Adapter
的数据时会出现一会的白屏现象,这就是执行动画造成的。或者我们删除ItemView会有一个很小的时间差,这也是动画的效果。调用以下Adapter
方法会触发ItemView
的动画
//会触动动画的更新
adapter.notifyItemInserted(1);
adapter.notifyItemRemoved(1);
adapter.notifyItemChanged(1);
adapter.notifyItemMoved(1, 2);
// 不会触发动画的更新
adapter.notifyDataSetChanged();
调用Adapter
的notify...(position)
方法就可以执行动画,不过要写上特定的位置或位置区间。
在最后有一个更新notifyDataSetChanged
是不会执行动画,原因是给ViewHolder
设置了无效状态,在测量时就拿不到旧ViewHolder
的信息,导致ItemView的动画不能执行。具体分析可以看上一篇RecyclerView的Adapter源码分析
动画源码
如果你不只是想自定义动画时间那么简单,而是想自己实现动画效果,那么最起码就要分析动画原来的源码。
public class RecyclerView extends ViewGroup implements ScrollingView,
NestedScrollingChild2, NestedScrollingChild3 {
// RecyclerView已经默认ItemAnimator的实例为DefaultItemAnimator
ItemAnimator mItemAnimator = new DefaultItemAnimator();
}
//谷歌默认实现的动画类
public class DefaultItemAnimator extends SimpleItemAnimator { }
public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator { }
public abstract static class ItemAnimator { }
RecyclerView
的动画实现类是DefaultItemAnimator
对象,而DefaultItemAnimator
并不是直接继承RecyclerView.ItemAnimator
,而是继承SimpleItemAnimator
抽象类。SimpleItemAnimator
抽象类才去继承RecyclerView.ItemAnimator
。
RecyclerView.ItemAnimator
RecyclerView.ItemAnimator
源码除了实现了动画执行时间外,其他的大多数都是提供一个抽象方法让其子类实现。其中有五个抽象方法比较重要
animateDisappearance
: View从可见区域到不可见区域,如View的删除-ReMove操作或滑动-Move操作到不可见区域
animateAppearance
: View从不可见区域到可见区域,如View的增加-Add操作或滑动-Move操作到可见区域
animateChange
:View的更新操作
animatePersistence
:此方法的调用时机是ItemView未进行任何操作。
runPendingAnimations
:开始执行动画方法
继承RecyclerView.ItemAnimator
需要重写什么方法?
public class SimplesItemAnimator extends RecyclerView.ItemAnimator {
// View从可见区域到不可见区域,如View的删除ReMove操作或滑动Move操作到不可见区域
@Override
public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
return false;
}
// View从不可见区域到可见区域,如View的增加Add操作或滑动Move操作到可见区域
@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder, @Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
return false;
}
// 此方法的调用时机是ItemView未进行任何操作。
@Override
public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
return false;
}
// View的更新操作
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder, @NonNull ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
return false;
}
// 开始执行动画操作
@Override
public void runPendingAnimations() {
}
// 结束ViewHolder的动画
@Override
public void endAnimation(@NonNull RecyclerView.ViewHolder item) {
}
// 结束动画
@Override
public void endAnimations() {
}
// 是否在运行
@Override
public boolean isRunning() {
return false;
}
}
重写的方法好挺多,接下来看看谷歌提供的实例是如何重写的。
SimpleItemAnimtor
其中SimpleItemAnimtor
就是谷歌实现的继承RecyclerView.ItemAnimator
的类,我们看看它是如何实现抽象方法的。
public abstract class SimpleItemAnimator extends RecyclerView.ItemAnimator {
private static final boolean DEBUG = false;
private static final String TAG = "SimpleItemAnimator";
boolean mSupportsChangeAnimations = true;
@SuppressWarnings("unused")
public boolean getSupportsChangeAnimations() {
return mSupportsChangeAnimations;
}
public void setSupportsChangeAnimations(boolean supportsChangeAnimations) {
mSupportsChangeAnimations = supportsChangeAnimations;
}
@Override
public boolean canReuseUpdatedViewHolder(@NonNull RecyclerView.ViewHolder viewHolder) {
return !mSupportsChangeAnimations || viewHolder.isInvalid();
}
// 判断新旧的左上位置是否相同,不相同执行Move动画,相同执行ReMove动画
@Override
public boolean animateDisappearance(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
int oldLeft = preLayoutInfo.left;
int oldTop = preLayoutInfo.top;
View disappearingItemView = viewHolder.itemView;
int newLeft = postLayoutInfo == null ? disappearingItemView.getLeft() : postLayoutInfo.left;
int newTop = postLayoutInfo == null ? disappearingItemView.getTop() : postLayoutInfo.top;
// !isRemoved() 和 新旧的 左或上位置不相同
if (!viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) {
disappearingItemView.layout(newLeft, newTop,
newLeft + disappearingItemView.getWidth(),
newTop + disappearingItemView.getHeight());
if (DEBUG) {
Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView);
}
// 调用移动抽象方法
return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop);
} else {
if (DEBUG) {
Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView);
}
// 调用删除抽象方法
return animateRemove(viewHolder);
}
}
// 判断新旧的viewHolder的左上位置是否相同,不相同执行move动画,相同执行Add动画
@Override
public boolean animateAppearance(@NonNull RecyclerView.ViewHolder viewHolder,
@Nullable ItemHolderInfo preLayoutInfo, @NonNull ItemHolderInfo postLayoutInfo) {
// preLayoutInfo位置信息不null 和 新旧的 左或上位置不相同
if (preLayoutInfo != null && (preLayoutInfo.left != postLayoutInfo.left
|| preLayoutInfo.top != postLayoutInfo.top)) {
// slide items in if before/after locations differ
if (DEBUG) {
Log.d(TAG, "APPEARING: " + viewHolder + " with view " + viewHolder);
}
// 调用移动抽象方法
return animateMove(viewHolder, preLayoutInfo.left, preLayoutInfo.top,
postLayoutInfo.left, postLayoutInfo.top);
} else {
if (DEBUG) {
Log.d(TAG, "ADDED: " + viewHolder + " with view " + viewHolder);
}
// 调用增加抽象方法
return animateAdd(viewHolder);
}
}
// 如果新旧Viewholder的左上位置不相同执行Move动画,相同则结束动画
@Override
public boolean animatePersistence(@NonNull RecyclerView.ViewHolder viewHolder,
@NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
// 新旧的 左或上位置不相同
if (preInfo.left != postInfo.left || preInfo.top != postInfo.top) {
if (DEBUG) {
Log.d(TAG, "PERSISTENT: " + viewHolder
+ " with view " + viewHolder.itemView);
}
// 调用移动抽象方法
return animateMove(viewHolder,
preInfo.left, preInfo.top, postInfo.left, postInfo.top);
}
// 结束viewHolder的动画
dispatchMoveFinished(viewHolder);
return false;
}
// 执行Change动画
@Override
public boolean animateChange(@NonNull RecyclerView.ViewHolder oldHolder, @NonNull RecyclerView.ViewHolder newHolder,
@NonNull ItemHolderInfo preInfo, @NonNull ItemHolderInfo postInfo) {
if (DEBUG) {
Log.d(TAG, "CHANGED: " + oldHolder + " with view " + oldHolder.itemView);
}
final int fromLeft = preInfo.left;
final int fromTop = preInfo.top;
final int toLeft, toTop;
// 设置toLeft, toTop的值
if (newHolder.shouldIgnore()) {
// newHolder应该忽略,则使用旧ViewHolder的位置
toLeft = preInfo.left;
toTop = preInfo.top;
} else {
// 否则使用新ViewHolder的位置
toLeft = postInfo.left;
toTop = postInfo.top;
}
// 调用更新的抽象方法
return animateChange(oldHolder, newHolder, fromLeft, fromTop, toLeft, toTop);
}
// -> 提供了Remove抽象方法
public abstract boolean animateRemove(RecyclerView.ViewHolder holder);
// -> 提供了Add抽象方法
public abstract boolean animateAdd(RecyclerView.ViewHolder holder);
// -> 提供了Move抽象方法
public abstract boolean animateMove(RecyclerView.ViewHolder holder, int fromX, int fromY,
int toX, int toY);
// -> 提供了Change抽象方法
public abstract boolean animateChange(RecyclerView.ViewHolder oldHolder,
RecyclerView.ViewHolder newHolder, int fromLeft, int fromTop, int toLeft, int toTop);
// -> dispatchAnimationFinished真正实现关闭的方法,其他方法只是对外提供开始结束的方法
public final void dispatchRemoveFinished(RecyclerView.ViewHolder item) {
onRemoveFinished(item);
dispatchAnimationFinished(item);
}
//... 省略一些动画开始结束的调用的方法,是提供给外部扩展的空方法。
}
在SimpleItemAnimator
类中,主要重写了ItemAnimtor
的animate...
系列方法,并在这个方法中根据新旧ViewHolder
的Left
和top
的位置是否相等来判断ItemView的状态
,并根据ItemView要执行的操作分别调用animateRemove,animateAdd ,animateMove ,animateChange
抽象方法。
DefaultItemAnimator
DefaultItemAnimator
就是继承SimpleItemAnimator
实现动画的最终执行效果,所以我们在自定义的时候也可以通过继承SimpleItemAnimator
实现动画的最终效果。
public class DefaultItemAnimator extends SimpleItemAnimator {
private static final boolean DEBUG = false;
private static TimeInterpolator sDefaultInterpolator;
// 装置全部动画的ViewHolder的相关信息集合
private ArrayList<RecyclerView.ViewHolder> mPendingRemovals = new ArrayList<>();
private ArrayList<RecyclerView.ViewHolder> mPendingAdditions = new ArrayList<>();
private ArrayList<MoveInfo> mPendingMoves = new ArrayList<>();
private ArrayList<ChangeInfo> mPendingChanges = new ArrayList<>();
// 将一种类型的执行动画开始前的ViewHolder集合装进来,集合动画结束后再移除掉
ArrayList<ArrayList<RecyclerView.ViewHolder>> mAdditionsList = new ArrayList<>();
ArrayList<ArrayList<MoveInfo>> mMovesList = new ArrayList<>();
ArrayList<ArrayList<ChangeInfo>> mChangesList = new ArrayList<>();
// 将ViewHolder执行动画前装进来,动画执行后移除
ArrayList<RecyclerView.ViewHolder> mAddAnimations = new ArrayList<>();
ArrayList<RecyclerView.ViewHolder> mMoveAnimations = new ArrayList<>();
ArrayList<RecyclerView.ViewHolder> mRemoveAnimations = new ArrayList<>();
ArrayList<RecyclerView.ViewHolder> mChangeAnimations = new ArrayList<>();
// 因为移动move复杂,Viewholder和位置信息封装成一个类
private static class MoveInfo {
public RecyclerView.ViewHolder holder;
public int fromX, fromY, toX, toY;
MoveInfo(RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
this.holder = holder;
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
}
// 因为change更新操作复杂,新旧ViewHolder和位置信息封装成一个类
private static class ChangeInfo {
public RecyclerView.ViewHolder oldHolder, newHolder;
public int fromX, fromY, toX, toY;
private ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder) {
this.oldHolder = oldHolder;
this.newHolder = newHolder;
}
ChangeInfo(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
this(oldHolder, newHolder);
this.fromX = fromX;
this.fromY = fromY;
this.toX = toX;
this.toY = toY;
}
@Override
public String toString() {
return "ChangeInfo{"
+ "oldHolder=" + oldHolder
+ ", newHolder=" + newHolder
+ ", fromX=" + fromX
+ ", fromY=" + fromY
+ ", toX=" + toX
+ ", toY=" + toY
+ '}';
}
}
@Override
public boolean animateRemove(final RecyclerView.ViewHolder holder) {
resetAnimation(holder); //为view设置差值器,结束holder的动画
mPendingRemovals.add(holder); // 增加一个holder到删除集合
return true;
}
// 真正执行移除remove动画的方法
private void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate();
mRemoveAnimations.add(holder); // 动画开始前将holder增加进mRemoveAnimations集合
// 为动画设置时间,并把透明度设置为1-0,设置动画监听
animation.setDuration(getRemoveDuration()).alpha(0).setListener(
new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchRemoveStarting(holder); // 向外提供的接口,此方法什么也没做
}
@Override
public void onAnimationEnd(Animator animator) {
// 动画结束后置空监听
animation.setListener(null);
view.setAlpha(1); //透明度设置为1
dispatchRemoveFinished(holder); //结束动画,并向外提供方法
mRemoveAnimations.remove(holder); //移除相关holder
dispatchFinishedWhenDone();
}
}).start();
}
// 增加add动画
@Override
public boolean animateAdd(final RecyclerView.ViewHolder holder) {
resetAnimation(holder); //为view设置差值器,结束holder的动画
holder.itemView.setAlpha(0); //设置透明度为0
mPendingAdditions.add(holder);//增加holder到mPendingAdditions集合中
return true;
}
// 执行增加add动画的真正方法
void animateAddImpl(final RecyclerView.ViewHolder holder) {
final View view = holder.itemView;
final ViewPropertyAnimator animation = view.animate();
mAddAnimations.add(holder); // 增加holder到mAddAnimations集合中
// 设置动画时间和透明度最后为0-1
animation.alpha(1).setDuration(getAddDuration())
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchAddStarting(holder);
}
@Override
public void onAnimationCancel(Animator animator) {
view.setAlpha(1);
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null); // 监听置空
dispatchAddFinished(holder);
mAddAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
// 移动move动画
@Override
public boolean animateMove(final RecyclerView.ViewHolder holder, int fromX, int fromY,
int toX, int toY) {
final View view = holder.itemView;
// fromX加上移动的距离
fromX += (int) holder.itemView.getTranslationX();
fromY += (int) holder.itemView.getTranslationY();
resetAnimation(holder);
int deltaX = toX - fromX;
int deltaY = toY - fromY;
//deltaX==0表示移动完成
if (deltaX == 0 && deltaY == 0) {
dispatchMoveFinished(holder);
return false;
}
// 设置还没移动完的距离
if (deltaX != 0) {
view.setTranslationX(-deltaX);
}
if (deltaY != 0) {
view.setTranslationY(-deltaY);
}
// 真正集合中添加
mPendingMoves.add(new MoveInfo(holder, fromX, fromY, toX, toY));
return true;
}
// 执行移动move动画的真正方法
void animateMoveImpl(final RecyclerView.ViewHolder holder, int fromX, int fromY, int toX, int toY) {
final View view = holder.itemView;
final int deltaX = toX - fromX;
final int deltaY = toY - fromY;
if (deltaX != 0) {
view.animate().translationX(0);
}
if (deltaY != 0) {
view.animate().translationY(0);
}
// TODO: make EndActions end listeners instead, since end actions aren't called when
// vpas are canceled (and can't end them. why?)
// need listener functionality in VPACompat for this. Ick.
final ViewPropertyAnimator animation = view.animate();
mMoveAnimations.add(holder);
// 设置动画执行的时间与距离 -deltaX-0
animation.setDuration(getMoveDuration()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchMoveStarting(holder);
}
@Override
public void onAnimationCancel(Animator animator) {
if (deltaX != 0) {
view.setTranslationX(0);
}
if (deltaY != 0) {
view.setTranslationY(0);
}
}
@Override
public void onAnimationEnd(Animator animator) {
animation.setListener(null);
dispatchMoveFinished(holder);
mMoveAnimations.remove(holder);
dispatchFinishedWhenDone();
}
}).start();
}
@Override
public boolean animateChange(RecyclerView.ViewHolder oldHolder, RecyclerView.ViewHolder newHolder,
int fromX, int fromY, int toX, int toY) {
// 如果旧ViewHolder与新ViewHolder相等,则给Move动画
if (oldHolder == newHolder) {
// Don't know how to run change animations when the same view holder is re-used.
// run a move animation to handle position changes.
return animateMove(oldHolder, fromX, fromY, toX, toY);
}
// 旧ViewHolder的位移和透明度
final float prevTranslationX = oldHolder.itemView.getTranslationX();
final float prevTranslationY = oldHolder.itemView.getTranslationY();
final float prevAlpha = oldHolder.itemView.getAlpha();
resetAnimation(oldHolder);
// 差值
int deltaX = (int) (toX - fromX - prevTranslationX);
int deltaY = (int) (toY - fromY - prevTranslationY);
// recover prev translation state after ending animation
// 给旧ViewHolder设置之前的位移和透明度
oldHolder.itemView.setTranslationX(prevTranslationX);
oldHolder.itemView.setTranslationY(prevTranslationY);
oldHolder.itemView.setAlpha(prevAlpha);
// 给新的Viewholder设置差值和透明度
if (newHolder != null) {
// carry over translation values
resetAnimation(newHolder);
newHolder.itemView.setTranslationX(-deltaX);
newHolder.itemView.setTranslationY(-deltaY);
newHolder.itemView.setAlpha(0);
}
mPendingChanges.add(new ChangeInfo(oldHolder, newHolder, fromX, fromY, toX, toY));
return true;
}
void animateChangeImpl(final ChangeInfo changeInfo) {
final RecyclerView.ViewHolder holder = changeInfo.oldHolder;
final View view = holder == null ? null : holder.itemView;
final RecyclerView.ViewHolder newHolder = changeInfo.newHolder;
final View newView = newHolder != null ? newHolder.itemView : null;
if (view != null) {
final ViewPropertyAnimator oldViewAnim = view.animate().setDuration(
getChangeDuration());
mChangeAnimations.add(changeInfo.oldHolder);
oldViewAnim.translationX(changeInfo.toX - changeInfo.fromX);
oldViewAnim.translationY(changeInfo.toY - changeInfo.fromY);
oldViewAnim.alpha(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchChangeStarting(changeInfo.oldHolder, true);
}
@Override
public void onAnimationEnd(Animator animator) {
oldViewAnim.setListener(null);
view.setAlpha(1);
view.setTranslationX(0);
view.setTranslationY(0);
dispatchChangeFinished(changeInfo.oldHolder, true);
mChangeAnimations.remove(changeInfo.oldHolder);
dispatchFinishedWhenDone();
}
}).start();
}
if (newView != null) {
final ViewPropertyAnimator newViewAnimation = newView.animate();
mChangeAnimations.add(changeInfo.newHolder);
newViewAnimation.translationX(0).translationY(0).setDuration(getChangeDuration())
.alpha(1).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animator) {
dispatchChangeStarting(changeInfo.newHolder, false);
}
@Override
public void onAnimationEnd(Animator animator) {
newViewAnimation.setListener(null);
newView.setAlpha(1);
newView.setTranslationX(0);
newView.setTranslationY(0);
dispatchChangeFinished(changeInfo.newHolder, false);
mChangeAnimations.remove(changeInfo.newHolder);
dispatchFinishedWhenDone();
}
}).start();
}
}
// 开始执行动画
@Override
public void runPendingAnimations() {
// 先将集合检查一遍,都为空的话就不执行动画了。
boolean removalsPending = !mPendingRemovals.isEmpty();
boolean movesPending = !mPendingMoves.isEmpty();
boolean changesPending = !mPendingChanges.isEmpty();
boolean additionsPending = !mPendingAdditions.isEmpty();
if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
// nothing to animate
return;
}
// First, remove stuff 首先,执行删除ReMove动画集合
for (RecyclerView.ViewHolder holder : mPendingRemovals) {
// 真正执行remove动画的在animateRemoveImpl方法
animateRemoveImpl(holder);
}
mPendingRemovals.clear(); //动画完毕后,清空集合
// Next, move stuff 第二是执行移动动画
if (movesPending) {
final ArrayList<MoveInfo> moves = new ArrayList<>();
moves.addAll(mPendingMoves); //临时变量装move动画集合
mMovesList.add(moves); // 装载move动画集合
mPendingMoves.clear(); // 真正集合被清空了
Runnable mover = new Runnable() {
@Override
public void run() {
for (MoveInfo moveInfo : moves) {
// 真正执行move动画是animateMoveImpl方法
animateMoveImpl(moveInfo.holder, moveInfo.fromX, moveInfo.fromY,
moveInfo.toX, moveInfo.toY);
}
moves.clear(); //动画执行后,临时变量被清空
mMovesList.remove(moves); //动画执行后,mMovesList移除集合
}
};
//如果有删除动画,则等到remove动画执行完,才开始执行移动动画。
if (removalsPending) {
View view = moves.get(0).holder.itemView;
ViewCompat.postOnAnimationDelayed(view, mover, getRemoveDuration());
} else {
mover.run();
}
}
// Next, change stuff, to run in parallel with move animations
// 第三步,执行更新change的动画集合
if (changesPending) {
// 临时变量
final ArrayList<ChangeInfo> changes = new ArrayList<>();
changes.addAll(mPendingChanges);
mChangesList.add(changes); //动画集合开始前装到mChangesList
mPendingChanges.clear(); // 真正集合清空
Runnable changer = new Runnable() {
@Override
public void run() {
for (ChangeInfo change : changes) {
// 真正执行change动画方法animateChangeImpl
animateChangeImpl(change);
}
changes.clear(); // 动画集合执行完后,清空临时变量
mChangesList.remove(changes);// 动画集合执行完后,mChangesList清除相关集合
}
};
// 如果有删除动画,则等动画执行后,才调用异步run方法
if (removalsPending) {
RecyclerView.ViewHolder holder = changes.get(0).oldHolder;
ViewCompat.postOnAnimationDelayed(holder.itemView, changer, getRemoveDuration());
} else {
changer.run();
}
}
// Next, add stuff 最后一步,增加add操作动画
if (additionsPending) {
// 临时变量集合
final ArrayList<RecyclerView.ViewHolder> additions = new ArrayList<>();
additions.addAll(mPendingAdditions);
mAdditionsList.add(additions); //集合执行之前,装进mAdditionsList
mPendingAdditions.clear(); // 清空真正集合
Runnable adder = new Runnable() {
@Override
public void run() {
for (RecyclerView.ViewHolder holder : additions) {
// 真正执行增加的动画方法
animateAddImpl(holder);
}
additions.clear();
mAdditionsList.remove(additions);
}
};
// add操作动画要在移除和移动更新动画执行完后才执行
if (removalsPending || movesPending || changesPending) {
long removeDuration = removalsPending ? getRemoveDuration() : 0;
long moveDuration = movesPending ? getMoveDuration() : 0;
long changeDuration = changesPending ? getChangeDuration() : 0;
long totalDelay = removeDuration + Math.max(moveDuration, changeDuration);
View view = additions.get(0).itemView;
ViewCompat.postOnAnimationDelayed(view, adder, totalDelay);
} else {
adder.run();
}
}
}
网友评论