RecyclerView拖拽item时如何保留原位置背景占位符
实现方案
出现原位置空白的原因是ItemTouchHelper默认会将被拖拽的ItemView从原布局剥离,绘制到屏幕上层作为浮动拖拽层,原位置没有渲染内容所以呈现空白。只要让原位置的Item在拖拽状态下渲染占位背景即可实现需求,不需要修改原有拖拽逻辑的核心结构,具体实现步骤如下:
- 在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 // ... 其他内容绑定 } }
- 修改你现有的
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 } }
- 提前准备
drag_placeholder_bg占位背景drawable即可,支持自定义为虚线边框、灰色填充等你需要的占位样式。
内容的提问来源于stack exchange,提问作者NRUSINGHA MOHARANA
相关产品推荐
相关产品推荐

