Proportional vs. Monospaced Numbers: When to use which one in order to avoid "Wiggling Labels"
extension UIFont {
fileprivate var monospacedDigitFont: UIFont {
let oldFontDescriptor = fontDescriptor
let newFontDescriptor = oldFontDescriptor.monospacedDigitFontDescriptor
return UIFont(descriptor: newFontDescriptor, size: 0)
}
}
extension UIFontDescriptor {
fileprivate var monospacedDigitFontDescriptor: UIFontDescriptor {
let fontDescriptorFeatureSettings = [[UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType, UIFontDescriptor.FeatureKey.typeIdentifier: kMonospacedNumbersSelector]]
let fontDescriptorAttributes = [UIFontDescriptor.AttributeName.featureSettings: fontDescriptorFeatureSettings]
let fontDescriptor = self.addingAttributes(fontDescriptorAttributes)
return fontDescriptor
}
}
SwiftUIには monospacedDigit
が存在しているが、0の表示がスラッシュ入りの0となってしまうためCTFontから同様の方法でFontを作成。
let attributes = [
kCTFontFeatureSettingsAttribute : [
kCTFontFeatureTypeIdentifierKey: kNumberSpacingType,
kCTFontFeatureSelectorIdentifierKey : kMonospacedNumbersSelector
]
]
let descriptor = CTFontDescriptorCreateWithAttributes(attributes as CFDictionary)
let font = CTFontCreateWithFontDescriptor(descriptor, 16, nil)
let f = Font(font)
というか、UIFontとCTFontはそのままキャスト可能だった。 ので、次のようにまとめた
extension Font {
static func customMonospacedDigit(size: CGFloat, weight: UIFont.Weight) -> Font {
Font(UIFont.systemFont(ofSize: size, weight: weight).monospacedDigitFont() as CTFont)
}
}
extension UIFont {
func monospacedDigitFont() -> UIFont {
let oldFontDescriptor = fontDescriptor
let newFontDescriptor = oldFontDescriptor.monospacedDigitFontDescriptor
return UIFont(descriptor: newFontDescriptor, size: 0)
}
}
extension UIFontDescriptor {
fileprivate var monospacedDigitFontDescriptor: UIFontDescriptor {
let fontDescriptorFeatureSettings = [
[UIFontDescriptor.FeatureKey.featureIdentifier: kNumberSpacingType,
UIFontDescriptor.FeatureKey.typeIdentifier: kMonospacedNumbersSelector]
]
let fontDescriptorAttributes = [
UIFontDescriptor.AttributeName.featureSettings: fontDescriptorFeatureSettings
]
let fontDescriptor = self.addingAttributes(fontDescriptorAttributes)
return fontDescriptor
}
}