android - 由于 ItemTouchHelper 和 DiffUtil 之间的冲突导致不需要的动画

标签 android android-recyclerview itemtouchhelper android-diffutils

我正在实现一个支持拖放的 RecyclerView。当一个项目被删除时,该项目的索引列将在 Room 数据库中更新以存储更新的排序。

我面临的问题是,当我在删除项目后调用 Room 数据库更新时,因为项目列表是 ViewModel 中的 LiveData 并通过 Databinding 绑定(bind)到 RecyclerView,DiffUtil 将在之后立即重新计算项目位置和内容,其中 1. 添加了新的不需要的动画和 2. 有时内容没有正确刷新。

ItemTouchHelper:

val helper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
    ItemTouchHelper.UP or ItemTouchHelper.DOWN or
            ItemTouchHelper.START or ItemTouchHelper.END, 0
) {

    var dragFrom = -1
    var dragTo = -1

    override fun onMove(
        recyclerView: RecyclerView, selected: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        val from = selected.adapterPosition
        val to = target.adapterPosition

        if (dragFrom == -1) {
            dragFrom = from
        }
        dragTo = to
        recyclerView.adapter?.notifyItemMoved(from, to)

        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    }

    override fun clearView(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder
    ) {

        if (dragFrom != -1 && dragTo != -1 && dragFrom != dragTo) {
            val fromId = myAdapter.getItemId(dragFrom)

            detailViewModel.updateItemIndex(fromId, calcNewIndex(dragFrom, dragTo))
        }

        super.clearView(recyclerView, viewHolder)
        dragFrom = -1
        dragTo = -1
    }
})
helper.attachToRecyclerView(binding.detailRecyclerview)

MyAdapter 中的 DiffUtil:

class NoteDiffCallback : DiffUtil.ItemCallback<MyNote>() {
    override fun areItemsTheSame(oldItem: MyNote, newItem: MyNote): Boolean {
        return oldItem.noteId == newItem.noteId
        //return true (replacing this will mostly fix the ItemTouchHelper issues, but also removes other animations that I want, such as inserting)
    }

    override fun areContentsTheSame(oldItem: MyNote, newItem: MyNote): Boolean {
        return oldItem == newItem
    }
}

我想更改它以使 DiffUtil 不干扰 ItemTouchHelper,但我仍想保留 DiffUtil 以在插入新音符时获得漂亮的动画效果。非常感谢您的建议。

最佳答案

诀窍是更新 ItemTouchHelper.Callback 中的 ListAdapter 项目,这样来自 Room 数据库的更新不会执行任何操作,因为项目已经相等。

class ItemTouchHelperCallback(val adapter: MyNoteAdapter) :
        ItemTouchHelper.Callback() { // you need a reference to your adapter

    ...
    
    override fun onMove(
        recyclerView: RecyclerView, selected: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        val from = selected.adapterPosition
        val to = target.adapterPosition

        if (dragFrom == -1) {
            dragFrom = from
        }
        dragTo = to
    
        val items = adapter.currentList.toMutableList()
        Collections.swap(items, from, to)
        adapter.submitList(items) // calls adapter.notifyItemMoved(), so we don't have to

        return true
    }

    ...
}

关于android - 由于 ItemTouchHelper 和 DiffUtil 之间的冲突导致不需要的动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62660822/

相关文章:

android - 从 SDCARD 应用后台资源

java/安卓 : editing an object after clone/duplicate also edits the original

android - 创建 RecyclerView 并加载图像的正确方法是什么?

android - 如何在 ViewPager2 中使用 ItemTouchHelper.SimpleCallback?

java - 子点击时自动关闭滑动菜单

android - 通知的振动和声音默认设置

android - RecyclerView 存储/恢复 Activity 之间的状态

android - 如何将 popupWindow 显示为 Recyclerview 行元素的下拉 onClick?

android - 使用 ItemTouchHelper 时如何在 RecyclerView 中取消拖动项目?

android - RecyclerView 滑动删除仍然显示可绘制不完整的滑动