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

iOS开发:如何使用UIBezierPath绘制指定规格的复选框图标?

嘿,我懂你这种卡在UIBezierPath绘制特定图标上的感受——尤其是这种有严格边界要求的复选框,既要贴合5×5的整体范围,又得让勾超出内部3×3区域,确实容易绕晕。我来给你捋清楚实现思路,再附上代码示例,应该能帮你快速搞定!

实现思路与代码示例

1. 先明确坐标与尺寸逻辑

UIKit的坐标系以左上角为原点,y轴向下延伸。我们把5×5的整体边界对应到按钮的bounds,通过比例适配保证在不同尺寸按钮上都能符合设计要求:

  • 单位长度:let unit = bounds.width / 5.0(以宽度为准,确保图标是正方形)
  • 内部3×3区域的原点:(unit, unit)(整体边界两边各留1单位的边距)

2. 绘制超出边界的复选框路径

这里以常见的“勾形”复选框为例,让勾的两端分别超出3×3的下边界和右边界,代码如下:

private func createCheckboxPath(in bounds: CGRect) -> UIBezierPath {
    let path = UIBezierPath()
    let unit = bounds.width / 5.0
    
    // 勾的起点:内部3×3区域的左下偏上位置
    let startPoint = CGPoint(x: unit, y: unit * 3)
    path.move(to: startPoint)
    
    // 第一个拐点:超出内部3×3的下边界(内部下边界为4*unit,延伸至4.5*unit)
    let middlePoint = CGPoint(x: unit * 2, y: unit * 4.5)
    path.addLine(to: middlePoint)
    
    // 第二个拐点:超出内部3×3的右边界(内部右边界为4*unit,延伸至4.5*unit)
    let endPoint = CGPoint(x: unit * 4.5, y: unit)
    path.addLine(to: endPoint)
    
    // 调整线条样式,让图标更圆润自然
    path.lineWidth = unit * 0.6
    path.lineCapStyle = .round
    path.lineJoinStyle = .round
    
    return path
}

3. 集成到自定义按钮中

创建一个UIButton子类,在draw(_:)方法里调用路径绘制逻辑,还可以添加调试用的边界虚线:

class CustomCheckboxButton: UIButton {
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
        // 可选:绘制5×5的边界虚线,方便调试对齐
        let borderPath = UIBezierPath(rect: rect)
        borderPath.lineWidth = 0.5
        borderPath.setLineDash([1, 1], count: 2, phase: 0)
        UIColor.lightGray.setStroke()
        borderPath.stroke()
        
        // 绘制复选框主体
        let checkboxPath = createCheckboxPath(in: rect)
        UIColor.black.setStroke()
        checkboxPath.stroke()
    }
    
    private func createCheckboxPath(in bounds: CGRect) -> UIBezierPath {
        // 插入上面的路径代码
    }
}

4. 处理CorelDRAW制作的加号图标

你用CorelDRAW做的加号图标,建议导出为PDF格式(矢量图,缩放不失真),然后通过以下方法转成UIBezierPath:

private func createPlusPath(from pdfName: String, in bounds: CGRect) -> UIBezierPath? {
    guard let url = Bundle.main.url(forResource: pdfName, withExtension: "pdf"),
          let pdfDoc = CGPDFDocument(url as CFURL),
          let page = pdfDoc.page(at: 1) else {
        return nil
    }
    
    let pageRect = page.getBoxRect(.mediaBox)
    let path = UIBezierPath()
    
    // 遍历PDF页面的路径元素,还原加号形状
    page.applyPDFPath { elements in
        for element in elements {
            switch element.type {
            case .moveTo:
                path.move(to: element.points[0])
            case .lineTo:
                path.addLine(to: element.points[0])
            case .curveTo:
                path.addCurve(to: element.points[2], controlPoint1: element.points[0], controlPoint2: element.points[1])
            case .closeSubpath:
                path.close()
            @unknown default:
                break
            }
        }
    }
    
    // 缩放路径到按钮边界,保持比例
    let scale = min(bounds.width / pageRect.width, bounds.height / pageRect.height)
    path.apply(CGAffineTransform(scaleX: scale, y: scale))
    
    return path
}

之后在按钮的draw(_:)方法里调用这个方法,设置颜色后绘制即可。

小提示

  • 如果你的复选框是“方框+勾”的样式,先绘制3×3的方框(路径为UIBezierPath(rect: CGRect(x: unit, y: unit, width: unit*3, height: unit*3))),再叠加勾的路径
  • 调试时可以打开Xcode的「Debug View Hierarchy」,直观查看路径的实际位置是否符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:40:11