单行UILabel调用sizeThatFits返回宽大于给定值是否合理?
UILabel sizeThatFits() 返回宽度超出给定值的问题
问题重现
配置单行UILabel的代码如下:
let label = UILabel() label.text = "Lorem ipsum dolor sit amet" label.numberOfLines = 1
当传入较小宽度调用sizeThatFits(size)时,返回的尺寸宽度总是大于给定值:
let labelSize = label.sizeThatFits(CGSize(width: 30, height: UILabel.noIntrinsicMetric)) // labelSize.width > 30
核心疑问
按常理,sizeThatFits()是否应返回小于或等于给定值的尺寸?
原因解析
sizeThatFits()的设计逻辑是返回视图在给定约束下能完整显示内容的最小尺寸。对于单行UILabel,其内部计算的固有内容尺寸(intrinsic content size)基于文本完整显示所需的宽度,即使传入的限制宽度不足以容纳全部文本,单行模式下UILabel不会自动截断文本以适配宽度,因此sizeThatFits()会返回能完整显示整个文本的宽度,而非被限制在传入的宽度值内。
针对你补充的其他方法现象:
textRect(forBounds:limitedToNumberOfLines:)返回宽度为0:该方法是UILabel内部用于计算文本绘制区域的方法,直接调用时如果未正确初始化label的布局状态(比如未设置字体、未赋予合理的初始bounds),会导致计算结果异常。systemLayoutSizeFitting()与sizeThatFits()结果一致:该方法底层同样基于视图的固有内容尺寸计算,因此单行UILabel场景下表现完全相同。
解决方案
若需要获取被限制在指定宽度内的尺寸,可通过以下两种方式实现:
方式1:通过布局约束限制后获取尺寸
先给label设置固定宽度,再调用sizeToFit():
label.frame = CGRect(x: 0, y: 0, width: 30, height: UILabel.noIntrinsicMetric) label.sizeToFit() // 此时label的宽度为30,高度适配单行文本
或者手动限制sizeThatFits()的返回结果:
let fullSize = label.sizeThatFits(CGSize(width: CGFloat.infinity, height: UILabel.noIntrinsicMetric)) let constrainedSize = CGSize(width: min(30, fullSize.width), height: fullSize.height)
方式2:直接计算文本的约束尺寸
使用boundingRect(with:options:attributes:context:)直接计算文本在指定宽度下的尺寸,指定单行相关选项:
let text = "Lorem ipsum dolor sit amet" let font = UIFont.systemFont(ofSize: 17) // 匹配UILabel默认字体 let attributes: [NSAttributedString.Key: Any] = [.font: font] let constrainedSize = CGSize(width: 30, height: CGFloat.infinity) let textRect = text.boundingRect(with: constrainedSize, options: .usesLineFragmentOrigin, attributes: attributes, context: nil) // textRect.width ≤ 30,高度为单行文本所需高度,注意结果需向上取整以避免截断
内容的提问来源于stack exchange,提问作者clns
相关产品推荐
相关产品推荐

