RecyclerView拖拽移动,长按小图标拖拽,侧滑删除

RecyclerView拖拽移动,长按小图标拖拽,侧滑删除

Github源码


长按小图标拖拽.gif

侧滑删除.gif


  • Android RecyclerView出来也很多年了,是非常成熟的控件,Github上工具一堆,做的非常全,侧滑、拖拽、动画都封装好的,但是工作需求,这种小功能就不用别人的,自己学习一下,写一个简单的代码即可实现。

  • RecyclerView的拖拽跟侧滑删除,其实就是使用 ItemTouchHelper 来实现,而我们只要写一下CallBack 继承 ItemTouchHelper.Callback(),重写里面的方法就行。

  • 要注意的一点是,完成CallBack直接长按就能实现拖拽,但是点小图标拖拽,其实就是加个开关,item要使用ontouch回调来处理,而不要使用长按longClick回调,因为在三星手机上,onLongClick回调是在CallBack之后的,就会无法拖拽,而国产系统都是longClick先回调,坑了我一把。

  • 一定会重写的三个方法,功能如下。

/**
 * 设置拖拽、滑动方向
 */
override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
    if (!edit) {
        return 0
    }

    //拖拽方向
    val dragFlags =
        ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

    //侧滑删除
    val swipeFlags =  ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

    return makeMovementFlags(dragFlags, swipeFlags)
}

/**
 * 拖拽移动
 */
override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
    //不同类型的item不能移动
    if (viewHolder.itemViewType != target.itemViewType) {
        return false
    }

    //拖动的position
    var fromPosition = viewHolder.adapterPosition
    //释放的position
    var targetPosition = target.adapterPosition

    onCallBack.onMove(fromPosition, targetPosition)
    return true
}

/**
 * 侧滑
 */
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
    onCallBack.remove(viewHolder,direction,viewHolder.layoutPosition)
}
  • 按自己需求重写其他的方法,功能如下。
/**
 * 长按时调用
 */
override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
    super.onSelectedChanged(viewHolder, actionState)
    viewHolder?.let {
        //长按
        onCallBack.onSelectedChanged(viewHolder, actionState)
    }
}

/**
 * 松手时会最后调用
 */
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
    super.clearView(recyclerView, viewHolder)

    onCallBack.clearView(recyclerView, viewHolder)
}

/**
 * 是否支持长按,默认true
 */
override fun isLongPressDragEnabled(): Boolean {
    return super.isLongPressDragEnabled()
}

/**
 * 是否支持侧滑,默认true
 */
override fun isItemViewSwipeEnabled(): Boolean {
    return super.isItemViewSwipeEnabled()
}

  • 当我们移动item,数据换位置,就要自己写逻辑了。
/**
 * 移动item
 *
 * @param fromPosition   长按的item,position
 * @param targetPosition 要到达的position
 */
fun itemMove(adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>, data: List<*>, fromPosition: Int, targetPosition: Int) {
    if (adapter == null || data.isEmpty()) {
        return
    }

    if (fromPosition < targetPosition) {
        for (i in fromPosition until targetPosition) {
            Collections.swap(data, i, i + 1)
        }
    } else {
        for (i in targetPosition until fromPosition) {
            Collections.swap(data, i, i + 1)
        }
    }
    adapter.notifyItemMoved(fromPosition, targetPosition)
}
  • 这整个callback就完成了。
class RecyclerTouchHelpCallBack(var onCallBack: OnHelperCallBack) : ItemTouchHelper.Callback() {
    //拖拽开关
    var edit = false


    /**
     * 设置拖拽、滑动方向
     */
    override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
        if (!edit) {
            return 0
        }

        //拖拽方向
        val dragFlags =
            ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

        //侧滑删除
        val swipeFlags =  ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT

        return makeMovementFlags(dragFlags, swipeFlags)
    }

    /**
     * 拖拽移动
     */
    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        //不同类型的item不能移动
        if (viewHolder.itemViewType != target.itemViewType) {
            return false
        }

        //拖动的position
        var fromPosition = viewHolder.adapterPosition
        //释放的position
        var targetPosition = target.adapterPosition

        onCallBack.onMove(fromPosition, targetPosition)
        return true
    }

    /**
     * 侧滑
     */
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        onCallBack.remove(viewHolder,direction,viewHolder.layoutPosition)
    }

    /**
     * 长按时调用
     */
    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        super.onSelectedChanged(viewHolder, actionState)
        viewHolder?.let {
            //长按
            onCallBack.onSelectedChanged(viewHolder, actionState)
        }
    }

    /**
     * 松手时会最后调用
     */
    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)

        onCallBack.clearView(recyclerView, viewHolder)
    }

    /**
     * 是否支持长按,默认true
     */
    override fun isLongPressDragEnabled(): Boolean {
        return super.isLongPressDragEnabled()
    }

    /**
     * 是否支持侧滑,默认true
     */
    override fun isItemViewSwipeEnabled(): Boolean {
        return super.isItemViewSwipeEnabled()
    }


    /**
     * 移动item
     *
     * @param fromPosition   长按的item,position
     * @param targetPosition 要到达的position
     */
    fun itemMove(adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>, data: List<*>, fromPosition: Int, targetPosition: Int) {
        if (adapter == null || data.isEmpty()) {
            return
        }

        if (fromPosition < targetPosition) {
            for (i in fromPosition until targetPosition) {
                Collections.swap(data, i, i + 1)
            }
        } else {
            for (i in targetPosition until fromPosition) {
                Collections.swap(data, i, i + 1)
            }
        }
        adapter.notifyItemMoved(fromPosition, targetPosition)
    }

    interface OnHelperCallBack {
        fun onMove(fromPosition: Int, targetPosition: Int)

        fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder, actionState: Int)

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

        fun remove(viewHolder: RecyclerView.ViewHolder, direction: Int, position: Int)
    }
}
  • 使用简单。
callback = RecyclerTouchHelpCallBack(object : RecyclerTouchHelpCallBack.OnHelperCallBack {
    override fun onMove(fromPosition: Int, targetPosition: Int) {
        //移动item
        callback.itemMove(adapter, adapter.mData, fromPosition, targetPosition)
    }

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder, actionState: Int) {
        //选中的改变样式
        viewHolder.itemView.alpha = 1f
        viewHolder.itemView.scaleX = 1.2f
        viewHolder.itemView.scaleY = 1.2f
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        //松手后不让操作,不然会点击全部范围拖拽
        callback.edit = false
        //完成移动,选中的改变样式
        adapter.mData
        viewHolder.itemView.alpha = 1f
        viewHolder.itemView.scaleX = 1f
        viewHolder.itemView.scaleY = 1f
    }

    override fun remove(viewHolder: RecyclerView.ViewHolder, direction: Int, position: Int) {
        // callback.edit = false,所以不会触发侧滑删除
       adapter.removeData(position)
    }
})

ItemTouchHelper(callback).attachToRecyclerView(rv_item)
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值