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
相关产品推荐
相关产品推荐

