欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

scrollView 嵌套 recyclerview 时 BaseQuickAdapter 九宫格图片拖拽到底部删除,

来源: 开发者 投稿于  被查看 21968 次 评论:50

scrollView 嵌套 recyclerview 时 BaseQuickAdapter 九宫格图片拖拽到底部删除,


九宫格图片布局,长按直接拖拽图片,长按时显示底部删除布局,拖拽到删除布局处松手可删除布局,最后添加按钮不可拖拽,基于 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、最后在回调监听中处理拖拽的动画和删除操作

 

用户评论