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

Android Kotlin:修改RecyclerView滑动删除方向为左滑至右

修改RecyclerView滑动删除方向为左滑至右(或支持自定义方向)

直接修改为左滑至右的版本

修改后的SwipeToDeleteCallback代码

abstract class SwipeToDeleteCallback(context: Context) : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.RIGHT) {

    private val deleteIcon = ContextCompat.getDrawable(context, R.drawable.ic_delete_white_24)
    private val intrinsicWidth = deleteIcon?.intrinsicWidth
    private val intrinsicHeight = deleteIcon?.intrinsicHeight
    private val background = GradientDrawable()
    private val color = ContextCompat.getColor(context, R.color.swipe_delete_color)
    private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    override fun onChildDraw(
        c: Canvas,
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        dX: Float,
        dY: Float,
        actionState: Int,
        isCurrentlyActive: Boolean
    ) {
        val itemView = viewHolder.itemView
        val itemHeight = itemView.bottom - itemView.top
        val isCanceled = dX == 0f && !isCurrentlyActive

        if (isCanceled) {
            // 清理左侧的绘制区域
            clearCanvas(c, itemView.left.toFloat(), itemView.top.toFloat(), itemView.left + dX, itemView.bottom.toFloat())
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            return
        }

        // 绘制删除背景
        background.setColor(this.color)
        background.cornerRadius = 20.0f
        // 背景区域从左侧开始,随dX滑动扩展
        background.setBounds(itemView.left, itemView.top, (itemView.left + dX).toInt(), itemView.bottom)
        background.draw(c)

        // 计算删除图标的位置
        val deleteIconTop = itemView.top + (itemHeight - intrinsicHeight!!) / 2
        val deleteIconMargin = (itemHeight - intrinsicHeight) / 2
        val deleteIconLeft = itemView.left + deleteIconMargin
        val deleteIconRight = itemView.left + deleteIconMargin + intrinsicWidth!!
        val deleteIconBottom = deleteIconTop + intrinsicHeight

        // 绘制删除图标
        deleteIcon?.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom)
        deleteIcon?.draw(c)

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
    }

    private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) {
        c?.drawRect(left, top, right, bottom, clearPaint)
    }
}

MainActivity调用代码(无需修改)

val swipeHandler = object : SwipeToDeleteCallback(this) {
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val adapter1 = recyclerView.adapter as StockCompanyListAdapter
        adapter1.removeAt(viewHolder.adapterPosition)
    }
}

val itemTouchHelper = ItemTouchHelper(swipeHandler)
itemTouchHelper.attachToRecyclerView(recyclerView)

支持自定义滑动方向的通用版本

如果需要灵活切换左滑/右滑删除,可使用以下通用版本:

通用版SwipeToDeleteCallback代码

abstract class SwipeToDeleteCallback(
    context: Context,
    private val swipeDirection: Int // 传入ItemTouchHelper.LEFT或ItemTouchHelper.RIGHT
) : ItemTouchHelper.SimpleCallback(0, swipeDirection) {

    private val deleteIcon = ContextCompat.getDrawable(context, R.drawable.ic_delete_white_24)
    private val intrinsicWidth = deleteIcon?.intrinsicWidth
    private val intrinsicHeight = deleteIcon?.intrinsicHeight
    private val background = GradientDrawable()
    private val color = ContextCompat.getColor(context, R.color.swipe_delete_color)
    private val clearPaint = Paint().apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) }

    override fun onMove(
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        target: RecyclerView.ViewHolder
    ): Boolean {
        return false
    }

    override fun onChildDraw(
        c: Canvas,
        recyclerView: RecyclerView,
        viewHolder: RecyclerView.ViewHolder,
        dX: Float,
        dY: Float,
        actionState: Int,
        isCurrentlyActive: Boolean
    ) {
        val itemView = viewHolder.itemView
        val itemHeight = itemView.bottom - itemView.top
        val isCanceled = dX == 0f && !isCurrentlyActive

        if (isCanceled) {
            // 根据方向清理对应区域
            if (swipeDirection == ItemTouchHelper.LEFT) {
                clearCanvas(c, itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat())
            } else {
                clearCanvas(c, itemView.left.toFloat(), itemView.top.toFloat(), itemView.left + dX, itemView.bottom.toFloat())
            }
            super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
            return
        }

        // 根据方向绘制背景
        background.setColor(this.color)
        background.cornerRadius = 20.0f
        if (swipeDirection == ItemTouchHelper.LEFT) {
            background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom)
        } else {
            background.setBounds(itemView.left, itemView.top, (itemView.left + dX).toInt(), itemView.bottom)
        }
        background.draw(c)

        // 根据方向计算图标位置
        val deleteIconTop = itemView.top + (itemHeight - intrinsicHeight!!) / 2
        val deleteIconMargin = (itemHeight - intrinsicHeight) / 2
        val deleteIconLeft: Int
        val deleteIconRight: Int

        if (swipeDirection == ItemTouchHelper.LEFT) {
            deleteIconLeft = itemView.right - deleteIconMargin - intrinsicWidth!!
            deleteIconRight = itemView.right - deleteIconMargin
        } else {
            deleteIconLeft = itemView.left + deleteIconMargin
            deleteIconRight = itemView.left + deleteIconMargin + intrinsicWidth!!
        }
        val deleteIconBottom = deleteIconTop + intrinsicHeight

        // 绘制图标
        deleteIcon?.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom)
        deleteIcon?.draw(c)

        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
    }

    private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) {
        c?.drawRect(left, top, right, bottom, clearPaint)
    }
}

调用方式(指定左滑至右)

val swipeHandler = object : SwipeToDeleteCallback(this, ItemTouchHelper.RIGHT) {
    override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
        val adapter1 = recyclerView.adapter as StockCompanyListAdapter
        adapter1.removeAt(viewHolder.adapterPosition)
    }
}

val itemTouchHelper = ItemTouchHelper(swipeHandler)
itemTouchHelper.attachToRecyclerView(recyclerView)

关键修改点说明

  1. 滑动方向参数:将ItemTouchHelper.SimpleCallback的第二个参数从ItemTouchHelper.LEFT改为ItemTouchHelper.RIGHT(或通过参数动态传入),这是控制滑动方向的核心。
  2. 背景绘制区域:左滑至右时,背景从Item左侧开始随滑动距离扩展,而非右侧。
  3. 图标位置计算:图标从Item左侧的margin位置绘制,而非右侧。
  4. 画布清理逻辑:取消滑动时,清理对应方向的绘制区域,避免界面残留。

内容的提问来源于stack exchange,提问作者coder 534

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 23:42:32