等宽字体与比例字体,解决文字闪烁
refer: Proportional vs. Monospaced Numbers: When to use which one in order to avoid “Wiggling Labels”
定义
等宽字体(英语:Monospaced Font)是指字符宽度相同的电脑字体。方块字基本上都作为等宽字体处理,如各个地区的汉字、日语假名的全角字符、韩语谚文音节等字符都是等宽的。 但是一些中文、日文字体中,由于同时涵盖西文字符,因此也含有比例字体,造成一个字体中两种类型混合的局面。
比例字体(英语:Proportional Font)是指字符宽度不尽相同的电脑字体。在传统西文活字印刷中使用的铅字,每个字母的字符宽度不太一样,如小写字母的i、j、l宽度明显较窄,而w、m明显较宽,但是这样做可以提高单词的可读性,这在铅字制作设计上称为比例字体。
如下图:
等宽字体
比例字体
倒计时文字闪烁
- iOS 原生计时器
界面稳定且顺畅
- 某款应用
数值闪烁,非常糟糕的实现
原因 :倒计时的文本使用了等宽与非等宽混合的字符
解决方案
首先可以确认上图的闪烁,是由于时间数值更新,虽然文本字数一样,但是宽度变了。所以,把数值部分的字体修改为等宽字体即可。当然需要尊重UI Designer
,但是这也是最好的解决方案。
- 使用系统字体
UIFont.monospacedDigitSystemFont(ofSize: weight: )
iOS 9之后,系统字体默认是比例字体。用这个方法,在夹杂数值的文本中,会使用等宽的字体来展示文字
- 使用
UIFontDescriptor
,定制字符的特性
把地址字符中的数字定制为等宽显示。使用feature type(featureIdentifier)
kNumberSpacingType
,Selectors(typeIdentifier)
为 kMonospacedNumbersSelector
。
import let CoreText.kMonospacedNumbersSelector
import let CoreText.kNumberSpacingType
extension UIFont {
var monospacedDigitsFont: UIFont {
let oldDescriptor = fontDescriptor
let feature = UIFontDescriptor.FeatureKey.featureIdentifier
let selector = UIFontDescriptor.FeatureKey.typeIdentifier
let attr: [[UIFontDescriptor.FeatureKey: Any]] = [
[feature: kNumberSpacingType, selector: kMonospacedNumbersSelector]
]
let newDescriptor = oldDescriptor.addingAttributes([.featureSettings: attr])
return UIFont(descriptor: newDescriptor, size: pointSize)
}
}
如果有其它的定制需求,可以查开TrueType feature type。每一个
feature type
都可以有不同的定制。例如: kStylisticAlternativesType 文字风格,kStylisticAltSevenOnSelector 即可以把𝐚
->𝑎
最终结果
从效果可以看出,UIFont.monospacedDigitSystemFont(ofSize: weight: )
数字是等宽字符,使用 不同字符集 ;使用UIFont.monospacedDigitsFont
数字是等宽字符,使用 相同的字符集 ;使用UIFont.systemFont(ofSize:)
数字是比例字符。
但是也要注意,可能有些字体不支持等宽数字。这种情况下就可以使用
NSAttributedString
, 数字部分使用等宽字符。