You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RecyclerView拖拽item时如何保留原位置背景占位符

实现方案

出现原位置空白的原因是ItemTouchHelper默认会将被拖拽的ItemView从原布局剥离,绘制到屏幕上层作为浮动拖拽层,原位置没有渲染内容所以呈现空白。只要让原位置的Item在拖拽状态下渲染占位背景即可实现需求,不需要修改原有拖拽逻辑的核心结构,具体实现步骤如下:

  1. 在RecyclerView.Adapter中新增变量记录当前正在拖拽的位置,不需要侵入原有数据实体:
class YourAdapter(/* 原有构造参数 */) : RecyclerView.Adapter<YourViewHolder>() {
    // 记录当前拖拽的位置,默认-1代表无拖拽状态
    var currentDraggingPos: Int = -1
        set(value) {
            val oldPos = field
            field = value
            // 只刷新涉及状态变化的两个位置,避免全局刷新
            if (oldPos != -1) notifyItemChanged(oldPos, "DRAG_STATUS_UPDATE")
            if (value != -1) notifyItemChanged(value, "DRAG_STATUS_UPDATE")
        }

    // 重载带payload的绑定方法,局部刷新避免闪烁
    override fun onBindViewHolder(holder: YourViewHolder, position: Int, payloads: MutableList<Any>) {
        if (payloads.contains("DRAG_STATUS_UPDATE")) {
            val isDragging = position == currentDraggingPos
            // 仅更新背景和内容可见性,不重新绑定全部数据
            holder.itemView.setBackgroundResource(if (isDragging) R.drawable.drag_placeholder_bg else R.drawable.normal_item_bg)
            holder.contentRoot.visibility = if (isDragging) View.INVISIBLE else View.VISIBLE
            return
        }
        super.onBindViewHolder(holder, position, payloads)
    }

    override fun onBindViewHolder(holder: YourViewHolder, position: Int) {
        // 原有正常绑定逻辑不变
        val item = dataList[position]
        holder.titleTv.text = item.title
        // ... 其他内容绑定
    }
}
  1. 修改你现有的RecyclerViewDragDetector类,同步拖拽状态到Adapter:
abstract class RecyclerViewDragDetector(
    private val adapter: YourAdapter,
    dragDirs: Int = ItemTouchHelper.UP or ItemTouchHelper.DOWN or ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT,
    swipeDirs: Int = 0
) : ItemTouchHelper.SimpleCallback(dragDirs, swipeDirs) {

    override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
        // 拖拽过程中实时交换数据、更新列表位置
        val fromPos = viewHolder.adapterPosition
        val toPos = target.adapterPosition
        Collections.swap(adapter.dataList, fromPos, toPos)
        adapter.notifyItemMoved(fromPos, toPos)
        // 同步更新拖拽位置标记
        adapter.currentDraggingPos = toPos
        return true
    }

    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}

    override fun onSelectedChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
        super.onSelectedChanged(viewHolder, actionState)
        if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
            viewHolder?.let {
                // 标记拖拽起始位置
                adapter.currentDraggingPos = it.adapterPosition
                // 浮动拖拽层设置半透明
                it.itemView.alpha = 0.5f
            }
        }
    }

    override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
        super.clearView(recyclerView, viewHolder)
        // 拖拽结束清除状态标记
        adapter.currentDraggingPos = -1
        viewHolder.itemView.alpha = 1.0f
    }
}
  1. 提前准备drag_placeholder_bg占位背景drawable即可,支持自定义为虚线边框、灰色填充等你需要的占位样式。

内容的提问来源于stack exchange,提问作者NRUSINGHA MOHARANA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:09:05