You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 02:45:23