iOS下两个leading对齐不同字号UILabel 首字符为数字时出现缩进问题
问题原因
该问题和常见的横向相邻标签对齐问题的触发原因完全不同,是不同字号、字重的苹果旧金山动态字体自带的左侧字距预留(left side bearing)差异导致的:
为了实现不同字重、字号的文字视觉平衡,系统会给不同TextStyle、字重的字符预设不同的左侧留白,其中数字在semibold字重下的左侧预留值会明显大于regular字重的小字号文本。即使两个标签的leading约束已经严格对齐,文字实际渲染的起始点仍有差异,就会出现肉眼可见的缩进偏移。
修复方案
- 方案1:统一两个标签的文字对齐基准(最快修复)
给两个UILabel设置统一的段落样式,关闭默认的字距预留,强制文字从标签的leading边缘开始渲染:
// 通用段落样式配置,可抽成公共方法 let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.firstLineHeadIndent = 0 paragraphStyle.headIndent = 0 // 给上方caption1标签设置富文本 topLabel.attributedText = NSAttributedString( string: "你的文本内容", attributes: [ .font: UIFont.preferredFont(forTextStyle: .caption1, weight: .regular), .paragraphStyle: paragraphStyle ] ) // 给下方body标签设置富文本 bottomLabel.attributedText = NSAttributedString( string: "你的内容", attributes: [ .font: UIFont.preferredFont(forTextStyle: .body, weight: .semibold), .paragraphStyle: paragraphStyle ] )
如果不需要支持动态字体大小调整,也可以直接用UIFont.systemFont(ofSize: weight:)代替preferredFont,固定字号的字体字距预留差异会大幅缩小。
- 方案2:通过约束偏移补正(适合不想改富文本的场景)
计算下方标签字体的左侧预留值,把leading约束的偏移量减去这个值即可,需要先导入CoreText模块:
import CoreText // 拿到下方标签的字体 let bottomFont = UIFont.preferredFont(forTextStyle: .body, weight: .semibold) // 计算数字的左侧预留值作为修正偏移量 let offset = bottomFont.ctFont.leftSideBearing(for: "0") // 调整下方标签的leading约束 bottomLabel.leadingAnchor.constraint(equalTo: topLabel.leadingAnchor, constant: -offset).isActive = true
- 方案3:自定义UILabel子类统一处理(适合项目内多场景复用)
自定义无左侧边距的UILabel子类,自动修正不同字体的边距差异,两个标签都用该子类即可无需额外配置:
import CoreText class LeftAlignedNoPaddingLabel: UILabel { override func drawText(in rect: CGRect) { let fixOffset = font.ctFont.leftSideBearing(for: text?.first ?? "0") let insets = UIEdgeInsets(top: 0, left: -fixOffset, bottom: 0, right: 0) super.drawText(in: rect.inset(by: insets)) } }
内容的提问来源于stack exchange,提问作者LittlePeculiar
相关产品推荐
相关产品推荐

