九宫格图片布局,长按直接拖拽图片,长按时显示底部删除布局,拖拽到删除布局处松手可删除布局,最后添加按钮不可拖拽,基于 BaseQuickAdapter 基础上实现
BaseQuickAdapter 确实很好用,简化我们的实现代码,它本身也集成了一套拖拽实现,不过目前无法完美的满足上面的需求,需要做一些修改
1、首先自定义好九宫格布局,末尾是一个 + 号,这个加号无法拖拽,这里 + 号最好是用图片,更方便
2、在 adapter 中重写 addDraggableModule 方法,这里我直接自定义了自己的 DraggableModule ,因为我需要替换默认的监听事件,达到我自己的目的
核心逻辑就集中在 PhotoDraggableModule 中,否则自带的拖拽没发监听拖拽的距离,不好计算是否拖拽到了底部
源码中在 module 初始化的时候就已经把监听初始化了,所以在不替换的情况下,很难达到自己的需求
其实就是 DragAndSwipeCallback ,自己定义有点麻烦,还不如不用这套拖拽封装了,所以为了简化,只能继续用它,在它的基础上计算自己的拖拽距离就行了
直接在 module 中的 init 方法里 重新创建监听,去替换原有的 callback,这样就方便自己获取数据操作了
init { itemTouchHelperCallback = object : DragAndSwipeCallback(this) { override fun onChildDraw( c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean ) { super.onChildDraw( c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive ) if (callBack == null) return if (isCurrentlyActive) { viewHolder.itemView.visibility = View.VISIBLE if (dY.toInt() == 0) { isDel = false callBack?.touchStart() } else if (dY > 0) { //拖到指定区域 val bottom = (recyclerView.parent.parent as View).bottom + dY val bottomY = bottom - (recyclerView.bottom - viewHolder.itemView.bottom) - (scrollView?.scrollY ?: 0) //是否在删除区域 isDel = bottomY >= bottomDelTopY callBack?.touchMove(isDel) } } else { val delPosition = if (isDel) viewHolder.layoutPosition else null //松开先隐藏,预防松开后item回到列表在执行删除动画 viewHolder.itemView.visibility = if (isDel) View.INVISIBLE else View.VISIBLE callBack?.touchUp(delPosition) isDel = false } } @SuppressLint("NotifyDataSetChanged") override fun clearView( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder ) { super.clearView(recyclerView, viewHolder) viewHolder.itemView.visibility = View.VISIBLE //等待布局操作结束执行刷新,避免下方异常 //Cannot call this method while RecyclerView is computing a layout or scroll viewHolder.itemView.post { baseQuickAdapter.notifyDataSetChanged() } } } itemTouchHelper = ItemTouchHelper(itemTouchHelperCallback) }
3、计算拖拽距离
如果没有被 scrollView 嵌套,直接通过拖拽的距离就能判断是否到底部了,但是一般情况下都需要你可滑动,就会需要嵌套一层 scrollVIew
根据上面代码看出,其实就是需要获取 scrollView 的滚动距离,从中得出你拖拽的距离是否到底部了,这里用 isDel 来控制执行次数,否则会重复调用多次
4、最后在回调监听中处理拖拽的动画和删除操作