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

Swift中如何使用UIBezierPath绘制黑色内凹圆角矩形

Swift 使用UIBezierPath绘制指定内凹圆角矩形(仅黑色填充区域)

内凹圆角矩形参考示意图

核心逻辑很简单:普通外凸圆角的圆弧圆心在矩形内部,内凹圆角的四个圆弧圆心刚好对应矩形的四个顶点,用四分之一圆弧连接相邻两条直边,闭合路径后直接填充即可得到目标黑色区域,不需要做挖空处理。

绘制规则

  • 先确定两个基础参数:形状的外接矩形范围bounds、内凹圆角半径cornerRadius,注意圆角半径不能超过矩形宽度/高度的1/2,否则路径会出现错乱。
  • 按顺时针方向依次绘制边和圆弧:
    • 从顶部直边的左端点(x: bounds.minX + cornerRadius, y: bounds.minY)开始,画直线到顶部直边右端点(x: bounds.maxX - cornerRadius, y: bounds.minY)
    • 右上角绘制内凹圆弧:圆心为矩形右上角顶点(x: bounds.maxX, y: bounds.minY),半径为cornerRadius,连接顶部直边右端点和右侧直边上端点
    • 从右侧直边上端点画直线到右侧直边下端点(x: bounds.maxX, y: bounds.maxY - cornerRadius)
    • 右下角绘制内凹圆弧:圆心为矩形右下角顶点(x: bounds.maxX, y: bounds.maxY),半径为cornerRadius,连接右侧直边下端点和底部直边右端点
    • 从底部直边右端点画直线到底部直边左端点(x: bounds.minX + cornerRadius, y: bounds.maxY)
    • 左下角绘制内凹圆弧:圆心为矩形左下角顶点(x: bounds.minX, y: bounds.maxY),半径为cornerRadius,连接底部直边左端点和左侧直边下端点
    • 从左侧直边下端点画直线到左侧直边上端点(x: bounds.minX, y: bounds.minY + cornerRadius)
    • 左上角绘制内凹圆弧:圆心为矩形左上角顶点(x: bounds.minX, y: bounds.minY),半径为cornerRadius,连接左侧直边上端点和最开始的路径起点
    • 闭合路径后填充黑色即可

可直接复用的代码示例

import UIKit

class InvertedRoundedRectView: UIView {
    /// 内凹圆角半径,可按需修改
    var cornerRadius: CGFloat = 20 {
        didSet { setNeedsDisplay() }
    }
    /// 填充色,默认就是要求的黑色
    var fillColor: UIColor = .black {
        didSet { setNeedsDisplay() }
    }

    override func draw(_ rect: CGRect) {
        let path = UIBezierPath()
        // 圆角半径容错处理,避免超过宽高上限导致路径异常
        let safeRadius = min(cornerRadius, rect.width / 2, rect.height / 2)
        
        // 移动到顶边起点
        path.move(to: CGPoint(x: rect.minX + safeRadius, y: rect.minY))
        // 绘制顶边
        path.addLine(to: CGPoint(x: rect.maxX - safeRadius, y: rect.minY))
        // 绘制右上角内凹弧
        path.addArc(
            withCenter: CGPoint(x: rect.maxX, y: rect.minY),
            radius: safeRadius,
            startAngle: .pi,
            endAngle: .pi / 2,
            clockwise: false
        )
        // 绘制右边
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - safeRadius))
        // 绘制右下角内凹弧
        path.addArc(
            withCenter: CGPoint(x: rect.maxX, y: rect.maxY),
            radius: safeRadius,
            startAngle: .pi * 3 / 2,
            endAngle: .pi,
            clockwise: false
        )
        // 绘制底边
        path.addLine(to: CGPoint(x: rect.minX + safeRadius, y: rect.maxY))
        // 绘制左下角内凹弧
        path.addArc(
            withCenter: CGPoint(x: rect.minX, y: rect.maxY),
            radius: safeRadius,
            startAngle: 0,
            endAngle: .pi * 3 / 2,
            clockwise: false
        )
        // 绘制左边
        path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + safeRadius))
        // 绘制左上角内凹弧
        path.addArc(
            withCenter: CGPoint(x: rect.minX, y: rect.minY),
            radius: safeRadius,
            startAngle: .pi / 2,
            endAngle: 0,
            clockwise: false
        )
        // 闭合路径
        path.close()
        
        // 填充颜色
        fillColor.setFill()
        path.fill()
    }
}

注意:代码中addArc方法的clockwise参数固定传false,是因为UIKit坐标系的Y轴方向和数学坐标系相反(向下为正),如果传true会画出向外凸的普通圆角,和预期效果不符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:24:22