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

Android ItemTouchHelper 滑动RecyclerView条目时如何绘制逐步放大的圆形

实现RecyclerView滑动时圆形扩散背景的方案

核心实现逻辑

  • 基于滑动距离计算滑动进度,将进度映射为圆形半径,实现随滑动放大的效果
  • 直接使用Canvas.drawCircle绘制圆形,避免Drawable宽高不一致导致的拉伸变形问题
  • 裁剪画布绘制区域,限制圆形仅在当前条目范围内显示,不会覆盖其他列表项

完整实现代码

提前初始化画笔和图标,避免在绘制方法中重复创建影响性能:

// 提前初始化背景画笔
private val backgroundPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.parseColor("#ba000d")
}
// 提前加载删除图标
private val deleteIcon: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_baseline_delete_24)

override fun onChildDraw(
    c: Canvas,
    recyclerView: RecyclerView,
    viewHolder: RecyclerView.ViewHolder,
    dX: Float,
    dY: Float,
    actionState: Int,
    isCurrentlyActive: Boolean
) {
    val itemView = viewHolder.itemView
    // 仅处理左滑逻辑,右滑可修改判断条件为dX<=0
    if (actionState != ItemTouchHelper.ACTION_STATE_SWIPE || dX >= 0) {
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
        return
    }

    // 1. 计算滑动进度,范围0~1
    val swipeProgress = abs(dX) / itemView.width.coerceAtLeast(1)
    val progress = swipeProgress.coerceAtMost(1f)

    // 2. 计算圆形参数:圆心为当前条目中心点,最大半径为刚好覆盖整个条目的半径
    val centerX = itemView.left + itemView.width / 2f
    val centerY = itemView.top + itemView.height / 2f
    val maxRadius = hypot(itemView.width / 2f, itemView.height / 2f)
    val currentRadius = maxRadius * progress

    // 3. 裁剪画布,限制绘制范围仅为当前条目区域
    c.save()
    c.clipRect(itemView.left, itemView.top, itemView.right, itemView.bottom)

    // 4. 绘制扩散圆形背景
    c.drawCircle(centerX, centerY, currentRadius, backgroundPaint)

    // 5. 绘制删除图标,固定在条目右侧垂直居中
    deleteIcon?.let { icon ->
        val iconSize = icon.intrinsicHeight
        val iconMargin = (itemView.height - iconSize) / 2
        val iconLeft = itemView.right - iconMargin - iconSize
        val iconTop = itemView.top + (itemView.height - iconSize) / 2
        icon.setBounds(iconLeft, iconTop, iconLeft + iconSize, iconTop + iconSize)
        // 图标随滑动进度逐步显示
        icon.alpha = (progress * 255).toInt()
        icon.draw(c)
    }

    c.restore()

    // 调用父类方法绘制滑动的条目内容,保证条目在背景上层
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
}

适配调整说明

  • 如果需要圆形从条目侧边而非中心点开始扩散,只需修改centerX的取值为对应侧边坐标即可
  • 如需修改圆形的颜色、图标样式,直接修改画笔颜色和图标资源即可

内容的提问来源于stack exchange,提问作者Steven Rathmann

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:03:01