当前位置:网站首页>RecycleView拖动效果

RecycleView拖动效果

2022-06-21 18:11:00 yufumatou

前言:基于RecycleView实现拖动效果,其实很简单,只需使用系统提供的ItemTouchHelper即可满足大部分需求。

实现:

1、创建ItemTouchHelper,在CallBack中处理业务

(1)getMovementFlags()设置允许拖动、滑动的方向

(2)onMove()拖动过程不断调用,用于交换item

(3)onSelectedChanged()长按选中回调,可以用作选中背景高亮

(4)clearView()结束拖动回调,可以用作还原选中背景

2、关联RecycleView,赋予滑动能力

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val tableList = ArrayList<String>()
        for (i in 1..200) {
            tableList.add("桌(${i})")
        }
        rv_table.layoutManager = GridLayoutManager(this, 5)
        TableAdapter().let {
            it.mTableList = tableList
            rv_table.adapter = it
        }
        val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
            override fun getMovementFlags(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ): Int {
                //拖动方向
                val dargFlags =
                    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //滑动方向
                val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //设置拖动、滑动方向
                return makeMovementFlags(dargFlags, swipeFlags)
            }

            override fun onMove(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder
            ): Boolean {
                //拖动的ViewHolder位置
                val fromPosition = viewHolder.adapterPosition
                //经过的ViewHolder位置
                val toPosition = target.adapterPosition
                when{
                    fromPosition < toPosition -> {//向后拖动,和位置+1进行交换
                        for (i in fromPosition..toPosition) {
                            Collections.swap(tableList, i, i + 1)
                        }
                        recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
                    }
                    fromPosition > toPosition -> {//向前拖动,和位置-1进行交换
                        for (i in fromPosition..toPosition) {
                            Collections.swap(tableList, i, i - 1)
                        }
                        recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
                    }
                }
                return true
            }

            override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
                super.onSelectedChanged(viewHolder, actionState)
                //长按选中更新要拖动的ViewHolder背景色
                (viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
            }

            override fun clearView(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ) {
                super.clearView(recyclerView, viewHolder)
                (viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
            }
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
        })
        //赋予RecycleView拖动能力
        itemTouchHelper.attachToRecyclerView(rv_table)
    }

进阶

场景一:禁止部分item拖动(如第1项禁止拖动)

1、禁用默认的拖动:CallBack中isLongPressDragEnabled()返回false

2、在自定义实现的item长按事件里,对于满足条件的执行拖动操作

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val tableList = ArrayList<String>()
        for (i in 1..200) {
            tableList.add("桌(${i})")
        }
        rv_table.layoutManager = GridLayoutManager(this, 5)
        val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
            override fun getMovementFlags(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ): Int {
                //拖动方向
                val dargFlags =
                    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //滑动方向
                val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //设置拖动、滑动方向
                return makeMovementFlags(dargFlags, swipeFlags)
            }

            override fun onMove(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder
            ): Boolean {
                //拖动的ViewHolder位置
                val fromPosition = viewHolder.adapterPosition
                //经过的ViewHolder位置
                val toPosition = target.adapterPosition
                when{
                    fromPosition < toPosition -> {//向后拖动,和位置+1进行交换
                        for (i in fromPosition..toPosition) {
                            Collections.swap(tableList, i, i + 1)
                        }
                        recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
                    }
                    fromPosition > toPosition -> {//向前拖动,和位置-1进行交换
                        for (i in fromPosition..toPosition) {
                            Collections.swap(tableList, i, i - 1)
                        }
                        recyclerView.adapter?.notifyItemMoved(fromPosition, toPosition)
                    }
                }
                return true
            }

            override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
                super.onSelectedChanged(viewHolder, actionState)
                //长按选中更新要拖动的ViewHolder背景色
                (viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
            }

            override fun clearView(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ) {
                super.clearView(recyclerView, viewHolder)
                (viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
            }

            override fun isLongPressDragEnabled(): Boolean {
                //禁用默认拖动
                return false
            }
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
        })
        //赋予RecycleView滑动能力
        itemTouchHelper.attachToRecyclerView(rv_table)
        TableAdapter().let {
            it.mTableList = tableList
            rv_table.adapter = it
            //将拖动职能传递给Adapter
            it.mItemTouchHelper = itemTouchHelper
        }
    }

class TableAdapter : RecyclerView.Adapter<TableAdapter.TableViewHolder>(){
    var mTableList = ArrayList<String>()
    var mItemTouchHelper: ItemTouchHelper? = null

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

    override fun onBindViewHolder(holder: TableViewHolder, position: Int) {
        val table = mTableList[position]
        holder.tvTabe.text = table
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_table, parent, false)
        return TableViewHolder(view)
    }

    inner class TableViewHolder constructor(view: View): RecyclerView.ViewHolder(view) {
        val tvTabe = view.findViewById<TextView>(R.id.tv_table)

        init {
            tvTabe.setOnLongClickListener {
                if (this.adapterPosition != 0){
                    mItemTouchHelper?.startDrag(this)
                    [email protected] true
                }
                [email protected] false
            }
        }
    }
}

场景二:只需将拖动的item和最终位置item进行交换,途径位置保持不变

1、在onMove()中将经过的位置记录到拖动的ViewHolder中

2、在clearView()中进行位置交换

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val tableList = ArrayList<String>()
        for (i in 1..200) {
            tableList.add("桌(${i})")
        }
        rv_table.layoutManager = GridLayoutManager(this, 5)
        val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() {
            override fun getMovementFlags(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ): Int {
                //拖动方向
                val dargFlags =
                    ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT or ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //滑动方向
                val swipeFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
                //设置拖动、滑动方向
                return makeMovementFlags(dargFlags, swipeFlags)
            }

            override fun onMove(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder,
                target: RecyclerView.ViewHolder
            ): Boolean {
                //经过的ViewHolder位置保存到拖动的ViewHolder中
                val toPosition = target.adapterPosition
                (viewHolder as TableAdapter.TableViewHolder).toPosition = toPosition
                return true
            }

            override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
                super.onSelectedChanged(viewHolder, actionState)
                //长按选中更新要拖动的ViewHolder背景色
                (viewHolder as? TableAdapter.TableViewHolder)?.tvTabe?.setBackgroundResource(R.color.colorPrimary)
            }

            override fun clearView(
                recyclerView: RecyclerView,
                viewHolder: RecyclerView.ViewHolder
            ) {
                super.clearView(recyclerView, viewHolder)
                (viewHolder as TableAdapter.TableViewHolder).tvTabe.setBackgroundResource(R.color.colorAccent)
                //拖动ViewHolder位置
                val fromPosition = viewHolder.adapterPosition
                //终点位置
                val toPosition = viewHolder.toPosition
                if (toPosition >= 0){
                    Collections.swap(tableList, fromPosition, toPosition)
                    recyclerView.adapter?.let{
                        it.notifyItemChanged(fromPosition)
                        it.notifyItemChanged(toPosition)
                    }
                }
            }

            override fun isLongPressDragEnabled(): Boolean {
                //禁用默认拖动
                return false
            }
            override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
        })
        //赋予RecycleView滑动能力
        itemTouchHelper.attachToRecyclerView(rv_table)
        TableAdapter().let {
            it.mTableList = tableList
            rv_table.adapter = it
            //将拖动职能传递给Adapter
            it.mItemTouchHelper = itemTouchHelper
        }
    }
class TableAdapter : RecyclerView.Adapter<TableAdapter.TableViewHolder>(){
    var mTableList = ArrayList<String>()
    var mItemTouchHelper: ItemTouchHelper? = null

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

    override fun onBindViewHolder(holder: TableViewHolder, position: Int) {
        val table = mTableList[position]
        holder.tvTabe.text = table
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TableViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.item_table, parent, false)
        return TableViewHolder(view)
    }

    inner class TableViewHolder constructor(view: View): RecyclerView.ViewHolder(view) {
        val tvTabe = view.findViewById<TextView>(R.id.tv_table)
        var toPosition = -1

        init {
            tvTabe.setOnLongClickListener {
                if (this.adapterPosition != 0){
                    mItemTouchHelper?.startDrag(this)
                    [email protected] true
                }
                [email protected] false
            }
        }
    }
}

原网站

版权声明
本文为[yufumatou]所创,转载请带上原文链接,感谢
https://blog.csdn.net/yufumatou/article/details/118251596