首页 > 解决方案 > 用于移动项目的 ItemTouchHelper 不起作用

问题描述

我正在实施 recyclerView 以更改项目顺序。为此,我正在使用 ItemTouchHelper。这是我的代码:

interface ItemTouchHelperAdapter {
    fun onItemMove(fromPosition: Int, toPosition: Int) : Boolean
    fun onItemDismiss(position: Int)
}

和帮助类,实现这个接口

class ItemTouchHelperCallback(private val adapter: ItemTouchHelperAdapter) : ItemTouchHelper.Callback() {

    override fun isLongPressDragEnabled(): Boolean {
        return true
    }

    override fun isItemViewSwipeEnabled(): Boolean {
        return true
    }

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

        val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
        val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END

        return makeMovementFlags(dragFlags, swipeFlags)
    }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        adapter.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
        return true
    }

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

另外,这是我的自定义 recyclerView 适配器

class ScansOrderAdapter(private val scans: MutableList<Scan>) :
    RecyclerView.Adapter<ScansOrderAdapter.ViewHolder>(), ItemTouchHelperAdapter {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.item_change_order,
                parent,
                false
            )
        )
    }

    override fun getItemCount(): Int {
        return scans.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        Glide.with(holder.itemView.item_image.context)
            .load(scans[position].filePath)
            .diskCacheStrategy(DiskCacheStrategy.NONE)
            .skipMemoryCache(true)
            .into(holder.itemView.item_image)
    }

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean {
        Collections.swap(scans, fromPosition, toPosition)
        notifyItemMoved(fromPosition, toPosition)

        return true
    }

    override fun onItemDismiss(position: Int) {
        if(scans.size != 0) {
            scans.removeAt(position)
            notifyItemRemoved(position)
        }
    }
} 

最后我正在设置适配器、布局管理器和 ItemTouchHelper:

fragment_change_scans_recycler.layoutManager = LinearLayoutManager(requireContext(),
        LinearLayoutManager.VERTICAL,
        false)

    val adapter = ScansOrderAdapter(scans)
    fragment_change_scans_recycler.adapter = ScansOrderAdapter(scans)

    val callback: ItemTouchHelper.Callback = ItemTouchHelperCallback(adapter)
    val touchHelper = ItemTouchHelper(callback)
    touchHelper.attachToRecyclerView(fragment_change_scans_recycler)

结果,我能够移动我的项目并滑动它们,所有回调都有效,我通过记录但测试了它,由于某些原因,其他项目没有更新它们的位置,也没有替换。我建议有什么问题notifyItemMoved(fromPosition, toPosition),也许我忘记了什么或者没有设置一些必需的属性。

标签: androidkotlin

解决方案


我发现了一个问题。它在这里:

  val adapter = ScansOrderAdapter(scans)
  fragment_change_scans_recycler.adapter = ScansOrderAdapter(scans)

  val callback: ItemTouchHelper.Callback = ItemTouchHelperCallback(adapter)
  val touchHelper = ItemTouchHelper(callback)
  touchHelper.attachToRecyclerView(fragment_change_scans_recycler)

修复方法是:

 val adapter = ScansOrderAdapter(scans)
 fragment_change_scans_recycler.adapter = adapter

推荐阅读