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

使用Path实现Android自定义View圆角时效果不符合预期

解决方案

问题出在CornerPathEffect的特性上——它会对路径上所有转角做统一的圆角处理,包括你特意绘制的左右切角圆弧的端点,直接破坏了原本的切角形状;同时左上角的路径衔接逻辑不对,加上这个效果后就变成了直线。要实现预期的“左右圆形切角+四角圆角”效果,必须手动精确绘制每一段路径,放弃使用CornerPathEffect。

修改后的完整代码

class RoundedRectUsingPath @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    private val roundCorner = 10f // 四角圆角半径
    private val avatarRadius = 30f // 左右切角半径

    private val paint = Paint().apply {
        color = Color.RED
        isAntiAlias = true
        setShadowLayer(10f, -2f, 2f, Color.BLACK)
        style = Paint.Style.FILL // 确保填充,阴影正常显示
    }

    private var path = Path()

    init {
        // 自定义Path的阴影需要关闭硬件加速,否则可能不显示
        setLayerType(LAYER_TYPE_SOFTWARE, null)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        val leftOffset = 10f
        val verticalOffset = 20f
        // 主体矩形的边界(去掉左右切角占用的空间)
        val mainRect = RectF(
            leftOffset + avatarRadius,
            verticalOffset,
            w - leftOffset - avatarRadius,
            h - verticalOffset
        )
        // 左切角的圆心和边界
        val leftCutCenter = PointF(leftOffset, mainRect.centerY())
        val leftCutRect = fromCircle(leftCutCenter, avatarRadius)
        // 右切角的圆心和边界
        val rightCutCenter = PointF(w - leftOffset, mainRect.centerY())
        val rightCutRect = fromCircle(rightCutCenter, avatarRadius)

        path.reset()
        path.apply {
            // 1. 左上角圆角:从圆角的右端点开始,绘制左上角的90度圆弧
            moveTo(mainRect.left + roundCorner, mainRect.top)
            arcTo(
                RectF(
                    mainRect.left, mainRect.top,
                    mainRect.left + roundCorner * 2, mainRect.top + roundCorner * 2
                ),
                180f, 90f, false
            )

            // 2. 连接到左切角的上端点,绘制左切角的180度圆弧(从顶部到底部)
            lineTo(leftCutRect.left, mainRect.top)
            arcTo(leftCutRect, -90f, 180f, false)

            // 3. 连接到左下角圆角的上端点,绘制左下角的90度圆弧
            lineTo(mainRect.left, mainRect.bottom)
            arcTo(
                RectF(
                    mainRect.left, mainRect.bottom - roundCorner * 2,
                    mainRect.left + roundCorner * 2, mainRect.bottom
                ),
                90f, 90f, false
            )

            // 4. 连接到右下角圆角的左端点,绘制右下角的90度圆弧
            lineTo(mainRect.right, mainRect.bottom)
            arcTo(
                RectF(
                    mainRect.right - roundCorner * 2, mainRect.bottom - roundCorner * 2,
                    mainRect.right, mainRect.bottom
                ),
                180f, 90f, false
            )

            // 5. 连接到右切角的下端点,绘制右切角的180度圆弧(从底部到顶部)
            lineTo(rightCutRect.right, mainRect.bottom)
            arcTo(rightCutRect, 90f, 180f, false)

            // 6. 连接到右上角圆角的下端点,绘制右上角的90度圆弧
            lineTo(mainRect.right, mainRect.top)
            arcTo(
                RectF(
                    mainRect.right - roundCorner * 2, mainRect.top,
                    mainRect.right, mainRect.top + roundCorner * 2
                ),
                270f, 90f, false
            )

            // 闭合路径
            close()
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        canvas.drawPath(path, paint)
    }

    // 保留你的辅助工具方法
    private fun fromLTRB(left: Float, top: Float, right: Float, bottom: Float) =
        RectF(left, top, right, bottom)

    private fun fromCircle(center: PointF, radius: Float) =
        fromLTRB(
            center.x - radius,
            center.y - radius,
            center.x + radius,
            center.y + radius
        )
}

关键改动说明

  1. 移除CornerPathEffect:放弃统一转角处理,改为手动绘制每个圆角和切角,完全控制形状。
  2. 拆分路径逻辑:把路径拆分为「四角圆角+左右切角」的分段绘制,确保每一段衔接无缝,每个圆弧的角度和范围都精确对应。
  3. 调整主体矩形边界:把主体矩形向中间收缩,留出左右切角的空间,避免路径重叠。
  4. 阴影适配:添加setLayerType(LAYER_TYPE_SOFTWARE, null),确保自定义Path的阴影能正常显示(硬件加速下自定义Path阴影可能失效)。

这样修改后,就能得到你想要的“左右圆形切角+四角完美圆角”的效果,不会出现变形或直线转角的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:40:55