随笔 - 129,  文章 - 3,  评论 - 50,  阅读 - 15万

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

 

posted on   翻滚的咸鱼  阅读(621)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示