RecyclerView条目删除动画优化:实现同步滑动效果
解决RecyclerView删除条目时的不同步滑动问题
默认RecyclerView的DefaultItemAnimator删除条目时,会先让目标条目消失,留下空白后才让下方条目上移,视觉体验差。要实现被删条目与下方条目同步消失滑动的效果,核心是调整ItemAnimator的动画执行逻辑,和LayoutManager无关,具体方案如下:
方案一:自定义同步动画的ItemAnimator
DefaultItemAnimator的问题在于移除动画和位移动画是串行执行的,我们可以重写它让两个动画并行:
class SyncRemoveItemAnimator : DefaultItemAnimator() { override fun runPendingAnimations() { // 先处理移除和位移的待执行动画,让它们同时启动 val pendingRemovals = ArrayList(mPendingRemovals) val pendingMoves = ArrayList(mPendingMoves) if (pendingRemovals.isNotEmpty()) { pendingRemovals.forEach { animateRemove(it) } mPendingRemovals.clear() } if (pendingMoves.isNotEmpty()) { pendingMoves.forEach { animateMove(it.first, it.second, it.third, it.fourth) } mPendingMoves.clear() } super.runPendingAnimations() } override fun animateRemove(holder: RecyclerView.ViewHolder): Boolean { // 给移除动画设置和位移动画一致的时长 holder.itemView.alpha = 1f holder.itemView.translationY = 0f holder.itemView.animate() .alpha(0f) .translationY(holder.itemView.height.toFloat()) .setDuration(moveDuration) .setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { holder.itemView.alpha = 1f holder.itemView.translationY = 0f dispatchRemoveFinished(holder) } }) return true } }
然后给RecyclerView设置这个Animator:
recyclerView.itemAnimator = SyncRemoveItemAnimator() // 统一动画时长,确保同步 recyclerView.itemAnimator?.removeDuration = 300 recyclerView.itemAnimator?.moveDuration = 300
方案二:调整DefaultItemAnimator的参数(快速生效)
如果不想自定义,也可以通过禁用变更动画并统一时长来优化:
val animator = DefaultItemAnimator() animator.supportsChangeAnimations = false animator.removeDuration = 300 animator.moveDuration = 300 recyclerView.itemAnimator = animator
这种方式能一定程度缩小延迟,但效果不如自定义Animator彻底。
核心逻辑说明
默认动画的问题是先执行完所有移除动画,再执行位移动画。要实现同步,必须让移除动画和下方条目的位移动画同时启动,并且保持相同的动画时长,这样就能让被删条目逐渐消失的同时,下方条目同步上移填补位置,消除空白区域。
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

