如何使用Swift绘制参考图中指定的特殊自定义形状?
Swift 绘制自定义异形的实现方案
这类不规则自定义图形的核心逻辑是先拆解轮廓路径,再通过系统提供的路径绘制API拼接闭合路径后填充颜色即可,主流的SwiftUI和UIKit框架都有原生支持,两种实现方式如下:
1. SwiftUI 实现
通过遵循Shape协议自定义形状结构,在path(in:)方法内拼接路径即可:
import SwiftUI struct CustomSpecialShape: Shape { func path(in rect: CGRect) -> Path { var path = Path() // 以下坐标参数可根据你需要的实际形状调整,所有数值均为相对当前视图尺寸的相对值,适配不同大小的渲染需求 // 起点:左侧上方 path.move(to: CGPoint(x: rect.minX, y: rect.minY + 24)) // 左上斜切边 path.addLine(to: CGPoint(x: rect.minX + 24, y: rect.minY)) // 顶部横边到右上曲线起点 path.addLine(to: CGPoint(x: rect.maxX - 72, y: rect.minY)) // 右上内凹曲线,调整control参数修改弧度 path.addQuadCurve( to: CGPoint(x: rect.maxX, y: rect.minY + 48), control: CGPoint(x: rect.maxX - 24, y: rect.minY + 12) ) // 右侧竖边到右下圆角起点 path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - 12)) // 右下圆角 path.addLine(to: CGPoint(x: rect.maxX - 12, y: rect.maxY)) // 底部横边到左下圆角起点 path.addLine(to: CGPoint(x: rect.minX + 12, y: rect.maxY)) // 左下圆角 path.addQuadCurve( to: CGPoint(x: rect.minX, y: rect.maxY - 12), control: CGPoint(x: rect.minX, y: rect.maxY) ) // 闭合路径 path.closeSubpath() return path } } // 调用示例 CustomSpecialShape() .fill(.darkGray) .frame(width: 320, height: 220)
如果需要精确匹配目标形状,只需要按比例把参考轮廓的顶点、曲线控制点映射到当前视图的rect坐标区间,替换对应参数即可。
2. UIKit 实现
通过UIBezierPath绘制路径,可直接在自定义View的draw(_:)方法渲染,也可生成CAShapeLayer挂载到视图上:
import UIKit class CustomShapeView: UIView { override func draw(_ rect: CGRect) { let path = UIBezierPath() // 路径拼接逻辑和SwiftUI完全一致 path.move(to: CGPoint(x: rect.minX, y: rect.minY + 24)) path.addLine(to: CGPoint(x: rect.minX + 24, y: rect.minY)) path.addLine(to: CGPoint(x: rect.maxX - 72, y: rect.minY)) path.addQuadCurve( to: CGPoint(x: rect.maxX, y: rect.minY + 48), controlPoint: CGPoint(x: rect.maxX - 24, y: rect.minY + 12) ) path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - 12)) path.addLine(to: CGPoint(x: rect.maxX - 12, y: rect.maxY)) path.addLine(to: CGPoint(x: rect.minX + 12, y: rect.maxY)) path.addQuadCurve( to: CGPoint(x: rect.minX, y: rect.maxY - 12), controlPoint: CGPoint(x: rect.minX, y: rect.maxY) ) path.close() // 填充深色 UIColor.darkGray.setFill() path.fill() } }
注意事项
- 路径参数全部使用相对rect的数值,不要写死绝对坐标,确保形状可以自适应不同的视图尺寸
- 如果形状曲线复杂度较高,可以用可视化路径生成工具导出参数,直接复制到代码中使用
- 需要添加阴影、描边等效果时,直接给SwiftUI的Shape加对应修饰符,或者给UIKit的CAShapeLayer设置对应属性即可
内容的提问来源于stack exchange,提问作者Oscar Junius
相关产品推荐
相关产品推荐

