字体与文本高度计算
2019-02-22 本文已影响0人
lsh_01
字体
在 iOS 9 中,新增了两个字体家族San Francisco(英文)
和PingFangSC(简体中文)
。
其中 San Francisco 分为.SFUIText
和.SFUIDisplay
两种字体;PingFangSC 分为PingFangSC-Regular
、PingFangSC-Light
和PingFangSC-Medium
三种字体。
在 iOS 9 之前,常用英文字体家族为Helvetica Neue
和Helvetica
;常用简体中文字体为STHeitiSC
。
其中 STHeitiSC 分为STHeitiSC-Light
和STHeitiSC-Medium
两种字体;STHeitiSC 字体家族在 iOS 9 中已被移除。
这四种字体的基本属性如下:(表格中的值均为系数,乘以字号可以得到真实的值)
属性 | .SFUIText / .SFUIDisplay | Helvetica Neue / Helvetica | PingFangSC | STHeitiSC-Light / STHeitiSC-Medium |
---|---|---|---|---|
ascender | 0.952148 | 0.952000 / 0.920020 | 1.060000 | 0.860000 |
capheight | 0.704590 | 0.714000 / 0.717285 | 0.860000 | 0.778000 / 0.718000 |
xheight | 0.526367 / 0.507812 | 0.517000 / 0.522949 | 0.600000 | 0.591000 / 0.531000 |
base-line | 0 | 0 | 0 | 0 |
descender | -0.241211 | -0.213000 / -0.229980 | -0.340000 | -0.140000 |
lineheight | 1.193359 | 1.165000 / 1.150000 | 1.400000 | 1.000000 |
leading | 0 | 0.028000 / 0 | 0 | 1.000000(0.03) |
.SFUIText 与 .SFUIDisplay 的差异主要是字体间距的不同,Text 字体间距较大,使得在小的字体中更加易读。
在APP里面使用了 SF 字体后,由操作系统自动选择使用 .SFUIText 还是 .SFUIDisplay。当字号小于20号时,选择 .SFUIText,否则选择 .SFUIDisplay。
文本高度计算
规则如下:
- 文本为空时,高度为字体的 lineHeight。
- 只有一行时,高度为字体的 lineHeight + leading。
- 如果 leading=0 且 lineSpacing>0,高度为 lineHeight * numOfLines + lineSpacing * (numOfLines - 1)。
- 如果 leading=0 且 lineSpacing<=0,高度为 lineHeight * numOfLines。
- 如果 leading>0 且 lineSpacing<-leading,高度为 lineHeight * numOfLines。
- 如果 leading>0 且 lineSpacing<0 且 lineSpacing>=-leading,高度为 lineHeight * numOfLines + (lineSpacing + leading) * (numOfLines - 1)。
- 如果 leading>0 且 lineSpacing>=0 且 lineSpacing<=leading,高度为 lineHeight * numOfLines + leading * (numOfLines - 1)。
- 如果 leading>0 且 lineSpacing>leading,高度为 lineHeight * numOfLines + lineHeight * (numOfLines - 1)。
代码:
func textHeight(numOfLines: Int, lineHeight: CGFloat, leading: CGFloat, lineSpacing: CGFloat) -> CGFloat {
if numOfLines == 0 {
return lineHeight
}
else if numOfLines == 1 {
return lineHeight + leading
}
if leading == 0 {
if linespacing > 0 {
return lineHeight * CGFloat(numOfLines) + linespacing * CGFloat(numOfLines - 1)
} else {
return lineHeight * CGFloat(numOfLines)
}
}
else if leading > 0 {
if linespacing < -leading {
return lineHeight * CGFloat(numOfLines)
}
else if linespacing < 0 {
return lineHeight * CGFloat(numOfLines) + (linespacing + leading) * CGFloat(numOfLines - 1)
}
else if linespacing <= leading {
return lineHeight * CGFloat(numOfLines) + leading * CGFloat(numOfLines - 1)
}
else {
return lineHeight * CGFloat(numOfLines) + linespacing * CGFloat(numOfLines - 1)
}
}
else {
fatalError("leading of font < 0")
}
}
其他需要注意的事项:
- 计算文本高度时,必须包含 NSStringDrawingUsesLineFragmentOrigin 参数,否则只能是单行。
- 计算文本高度时,如果不包含 NSStringDrawingUsesFontLeading 参数,leading 为 0;否则取字体的 leading。
- Heiti SC 的 leading 值为 1.00,但参与计算的值是 0.03。
- iOS 9 开始 Heiti SC 会被强制替换为 PingFangSC。
- 由于 Heiti SC 的 lineHeight=1,而 PingFangSC 的 lineHeight=1.4,iOS 9 前后的汉字行间距存在差异。
- iOS 9 开始默认英文字体为 SF 系列,原有的 Helvetica 系列仍然可以使用。
- San Francisco 系列中的 SF 用在 OS X 和 iOS 中,SF Compact 用在 Watch OS 中。