首页 > 解决方案 > 动画后 RecyclerView 项目重叠

问题描述

我有一个 RecyclerView 设置,我遇到了一个非常奇怪的问题,在某些适配器更新期间,RecyclerView 的项目相互重叠,就好像它们在动画中间停止动画一样。此问题似乎主要发生在移动项目时,但有时删除具有相同的效果。我最初的设置是使用AndroidXbeta01ListAdapter和 Room 作为我的应用程序数据库。我会简单地观察LiveData我会调用的观察方法内部的 andsubmitList()

我还应该注意,我添加了一个 RecyclerView.AdapterDataObserver 扩展onItemMoved并调用layoutManager.moveToPosition(0)以确保用户看到更新。

从那以后,我尝试了许多故障排除步骤,其中包括:

手动列表差异方法:

private fun calculateListDiffs(model: List<T>) {
        when {
            model.size > list.size -> {
                var i = 0

                while (i < itemCount) {
                    if (!areItemsSame(list[i], model[i])) {
                        list.add(i, model[i])
                        notifyItemInserted(i)
                    } else
                        i++
                }
            }
            model.size < list.size -> {
                var i = 0

                while (i < itemCount) {
                    when {
                        i >= model.size && !areItemsSame(list[i], model[model.size - 1]) -> {
                            list.removeAt(i)
                            notifyItemRemoved(i)
                        }
                        i < model.size && !areItemsSame(list[i], model[i]) -> {
                            list.removeAt(i)
                            notifyItemRemoved(i)
                        }
                        else -> i++
                    }
                }
            }
            else -> {
                run loop@{
                    for (i in 0 until itemCount) {
                        when {
                            !areItemsSame(list[i], model[i]) -> {
                                val pivot = model[i]

                                for (j in i until itemCount) {
                                    if (areItemsSame(list[j], pivot)) {
                                        list.removeAt(j)
                                        list.add(i, pivot)
                                        notifyItemMoved(j, i)
                                        notifyItemChanged(i)
                                        return@loop
                                    }
                                }
                            }
                            !areContentsSame(list[i], model[i]) -> {
                                list[i] = model[i]
                                notifyItemChanged(i)
                            }
                        }
                    }
                }
            }
        }
    }

问题仍然存在,经过所有这些测试,这似乎是适配器动画固有的问题,而不是 ListAdapter 或我自己的 diff 方法。

编辑:应该注意,由于我的应用程序的工作方式,收件箱中的项目需要移动到新位置并进行更新。所以也许打电话notifyItemMovednotifyItemChanged

标签: androidandroid-recyclerview

解决方案


来发现,奇怪的是,这是共享元素转换的问题。显然,在删除共享元素后,转换以某种方式导致 recyclerview 无法正确设置动画,一切都按预期运行。


推荐阅读