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

UIBezierPath在Storyboard与模拟器中绘制正方形显示为矩形问题

问题分析与解决方案

这个问题我之前做自定义IBDesignable控件时也踩过坑,核心原因大概率是控件布局变化时的内容缩放策略,或者没有基于当前控件尺寸动态计算单元格大小,咱们逐个排查:

1. 检查控件的contentMode设置

UIKit控件默认的contentMode是.scaleToFill,当控件的frame在运行时因AutoLayout调整发生变化时,系统会直接拉伸/缩放之前绘制好的内容,而不会重新调用draw(_ rect:)方法。这就导致IB里尺寸固定时绘制的正方形,在运行时被拉伸成矩形。

解决办法:
在控件的初始化方法里(比如init(frame:)或init(coder:))添加:

self.contentMode = .redraw

这样每次控件尺寸变化时,系统都会重新调用draw(_ rect:),保证绘制的内容适配新的尺寸。

2. 避免硬编码cellSize,基于控件动态尺寸计算

如果你的cellSize是固定的硬编码值(比如let cellSize = 20.0),那当控件在运行时的宽高和IB里的设置不一致时,整个网格的总尺寸和控件尺寸不匹配,就会被拉伸变形。

正确的做法是基于控件的bounds动态计算cellSize:

override func draw(_ rect: CGRect) {
    let columnCount = 7
    let rowCount = 7
    let space: Double = 2.0 // 替换成你的间隔值
    
    // 计算总间隔宽度/高度
    let totalHorizontalSpace = space * Double(columnCount - 1)
    let totalVerticalSpace = space * Double(rowCount - 1)
    
    // 取控件宽高中的较小值,保证网格整体为正方形
    let maxAvailableSize = min(Double(bounds.width), Double(bounds.height))
    
    // 计算单个单元格的尺寸
    let cellSize = (maxAvailableSize - max(totalHorizontalSpace, totalVerticalSpace)) / Double(max(columnCount, rowCount))
    
    // 执行绘制逻辑
    for i in 0 ..< columnCount {
        for j in 0 ..< rowCount {
            let x = Double(i) * (cellSize + space)
            let y = Double(j) * (cellSize + space)
            let rectangle = CGRect(x: x, y: y, width: cellSize, height: cellSize)
            let face = UIBezierPath(rect: rectangle)
            face.fill()
        }
    }
}

这样不管控件最终的尺寸是多少,网格都会适配控件大小,每个单元格保持正方形。

3. 确认控件的AutoLayout约束是否正确

如果你的控件在运行时的宽高比不是1:1,即使绘制的是正方形,也会因为控件本身被拉伸而显示成矩形。检查一下控件的约束:

  • 是否设置了宽高比为1:1的约束?
  • 是否有约束强制控件拉伸成非正方形?

如果希望控件本身保持正方形,一定要给它添加宽高比1:1的约束,或者在intrinsicContentSize里返回正方形的默认尺寸:

override var intrinsicContentSize: CGSize {
    return CGSize(width: 170, height: 170) // 替换成你期望的默认正方形尺寸
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:23:22