能否在UIFont层面修改kerning/leading/tracking?规避富文本大量改动
在UIFont层面调整Kerning/Tracking和Leading的方案
完全理解你的痛点——全量替换成富文本字符串确实会带来一堆额外的维护成本,还好我们可以通过UIFontDescriptor来直接在字体层面做这些调整,不用动原有标签的文本类型!
先明确几个概念(避免混淆)
- Tracking:全局字符间距调整(所有字符之间的间距统一放大/缩小),这是你大概率需要的“批量调整字距”需求。
- Kerning:针对特定字符对的间距优化(比如"AV"、"Ta"这类组合的精细调整),这个通常属于字体本身的内置特性,或者需要结合富文本的段落样式单独设置,而
UIFontDescriptor本身没有直接的全局kerning属性。 - Leading:行高相关的调整,可以通过字体描述符设置默认的行高倍数。
1. 给UIFont添加全局Tracking(字距)
用UIFontDescriptor.AttributeName.tracking这个键就能实现,值为NSNumber类型,正数增大间距,负数缩小:
// 基础自定义字体 let baseFont = UIFont(name: "CustomFont", size: 16)! // 创建带tracking的字体描述符 let trackedDescriptor = baseFont.fontDescriptor.addingAttributes([ .tracking: NSNumber(value: 0.4) // 这里的数值可根据需求调整,比如0.5、-0.2等 ]) // 生成最终字体 let fontWithTracking = UIFont(descriptor: trackedDescriptor, size: baseFont.pointSize) // 直接赋值给UILabel即可,不用改富文本 yourLabel.font = fontWithTracking
2. 调整Leading(行高)
可以通过UIFontDescriptor.AttributeName.lineHeightMultiple来设置行高倍数,让字体自带默认的行高比例:
let leadingDescriptor = baseFont.fontDescriptor.addingAttributes([ .lineHeightMultiple: NSNumber(value: 1.3) // 行高为原字体的1.3倍 ]) let fontWithLeading = UIFont(descriptor: leadingDescriptor, size: baseFont.pointSize) yourLabel.font = fontWithLeading
3. 封装成扩展,方便全局调用
为了减少重复代码,建议把这些逻辑封装成UIFont的扩展,后续开发直接调用就行:
extension UIFont { /// 给字体添加全局字距(Tracking) func withTracking(_ tracking: CGFloat) -> UIFont { let descriptor = self.fontDescriptor.addingAttributes([ .tracking: NSNumber(value: tracking) ]) return UIFont(descriptor: descriptor, size: self.pointSize) } /// 调整字体行高倍数 func withLineHeightMultiple(_ multiple: CGFloat) -> UIFont { let descriptor = self.fontDescriptor.addingAttributes([ .lineHeightMultiple: NSNumber(value: multiple) ]) return UIFont(descriptor: descriptor, size: self.pointSize) } } // 使用示例:一行代码搞定 let styledFont = UIFont(name: "CustomFont", size: 16)! .withTracking(0.3) .withLineHeightMultiple(1.2) yourLabel.font = styledFont
注意事项
- 部分自定义字体对tracking的支持可能有限,建议在不同字号下测试效果。
- 如果确实需要针对特定字符对调整kerning(而非全局字距),那还是得用富文本的
NSKernAttributeName,但这种场景一般比较少,全局tracking基本能覆盖大部分需求。 - 这种方式完全兼容原有代码,不用修改UILabel的文本类型(还是用普通
text属性),测试和维护成本都很低。
内容的提问来源于stack exchange,提问作者ldiqual
相关产品推荐
相关产品推荐

