如何获得符合辅助功能设置的等宽字体
How do I get a monospace font that respects acessibility settings
let bodyFontDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
let bodyMonospacedFontDescriptor = bodyFontDescriptor.addingAttributes(
[
UIFontDescriptorFeatureSettingsAttribute: [
[
UIFontFeatureTypeIdentifierKey: kTextSpacingType,
UIFontFeatureSelectorIdentifierKey: kMonospacedTextSelector
]
]
])
let bodyMonospacedFont = UIFont(descriptor: bodyMonospacedFontDescriptor, size: 0.0)
textview.font = bodyMonospacedFont
这会生成具有可变宽度字符的文本。
我需要在没有硬编码 courier new 的情况下获得等宽字体
和固定尺寸。
部署目标是 ios 9.0
这是 UIFontDescriptor
的扩展,returns 给定文本样式的首选等宽字体描述符。没有使用 UIFont
或 UIFontDescriptor
获得完全等宽字体的简单方法。此解决方案试图找到一个好的等宽字体,并在需要时回退到 Courier。
extension UIFontDescriptor {
static let monoDescriptor: UIFontDescriptor = {
// Attempt to find a good monospaced, non-bold, non-italic font
for family in UIFont.familyNames {
for name in UIFont.fontNames(forFamilyName: family) {
let f = UIFont(name: name, size: 12)!
let fd = f.fontDescriptor
let st = fd.symbolicTraits
if st.contains(.traitMonoSpace) && !st.contains(.traitBold) && !st.contains(.traitItalic) && !st.contains(.traitExpanded) && !st.contains(.traitCondensed) {
return fd
}
}
}
return UIFontDescriptor(name: "Courier", size: 0) // fallback
}()
class func preferredMonoFontDescriptor(withTextStyle style: UIFontTextStyle) -> UIFontDescriptor {
// Use the following line if you need a fully monospaced font
let monoDescriptor = UIFontDescriptor.monoDescriptor
// Use the following two lines if you only need monospaced digits in the font
//let monoDigitFont = UIFont.monospacedDigitSystemFont(ofSize: 0, weight: .regular)
//let monoDescriptor = monoDigitFont.fontDescriptor
// Get the non-monospaced preferred font
let defaultFontDescriptor = preferredFontDescriptor(withTextStyle: style)
// Remove any attributes that specify a font family or name and remove the usage
// This will leave other attributes such as size and weight, etc.
var fontAttrs = defaultFontDescriptor.fontAttributes
fontAttrs.removeValue(forKey: .family)
fontAttrs.removeValue(forKey: .name)
fontAttrs.removeValue(forKey: .init(rawValue: "NSCTFontUIUsageAttribute"))
let monospacedFontDescriptor = monoDescriptor.addingAttributes(fontAttrs)
return monospacedFontDescriptor.withSymbolicTraits(defaultFontDescriptor.symbolicTraits) ?? monospacedFontDescriptor
}
}
请注意关于您是需要完全等宽字体还是只有等宽数字的字体的评论。 Comment/Uncomment 满足您特定需求的那些行。
示例用法:
let bodyMonospacedFont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: .body), size: 0)
textview.font = bodyMonospacedFont
以下是一些测试代码,用于确认 preferredMonoFontDescriptor(withTextStyle:)
的结果适用于所有样式:
let textStyles: [UIFontTextStyle] = [ .body, .callout, .caption1, .caption2, .footnote, .headline, .subheadline, .largeTitle, .title1, .title2, .title3 ]
for style in textStyles {
let nfont = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: style), size: 0)
let mfont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: style), size: 0)
print(style)
print(nfont)
print(mfont)
}
如果比较每对结果,它们的大小、粗细和样式都相同,只是字体不同。
let bodyFontDescriptor = UIFontDescriptor
.preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
let bodyMonospacedFontDescriptor = bodyFontDescriptor.addingAttributes(
[
UIFontDescriptorFeatureSettingsAttribute: [
[
UIFontFeatureTypeIdentifierKey: kTextSpacingType,
UIFontFeatureSelectorIdentifierKey: kMonospacedTextSelector
]
]
])
let bodyMonospacedFont = UIFont(descriptor: bodyMonospacedFontDescriptor, size: 0.0)
textview.font = bodyMonospacedFont
这会生成具有可变宽度字符的文本。 我需要在没有硬编码 courier new 的情况下获得等宽字体 和固定尺寸。 部署目标是 ios 9.0
这是 UIFontDescriptor
的扩展,returns 给定文本样式的首选等宽字体描述符。没有使用 UIFont
或 UIFontDescriptor
获得完全等宽字体的简单方法。此解决方案试图找到一个好的等宽字体,并在需要时回退到 Courier。
extension UIFontDescriptor {
static let monoDescriptor: UIFontDescriptor = {
// Attempt to find a good monospaced, non-bold, non-italic font
for family in UIFont.familyNames {
for name in UIFont.fontNames(forFamilyName: family) {
let f = UIFont(name: name, size: 12)!
let fd = f.fontDescriptor
let st = fd.symbolicTraits
if st.contains(.traitMonoSpace) && !st.contains(.traitBold) && !st.contains(.traitItalic) && !st.contains(.traitExpanded) && !st.contains(.traitCondensed) {
return fd
}
}
}
return UIFontDescriptor(name: "Courier", size: 0) // fallback
}()
class func preferredMonoFontDescriptor(withTextStyle style: UIFontTextStyle) -> UIFontDescriptor {
// Use the following line if you need a fully monospaced font
let monoDescriptor = UIFontDescriptor.monoDescriptor
// Use the following two lines if you only need monospaced digits in the font
//let monoDigitFont = UIFont.monospacedDigitSystemFont(ofSize: 0, weight: .regular)
//let monoDescriptor = monoDigitFont.fontDescriptor
// Get the non-monospaced preferred font
let defaultFontDescriptor = preferredFontDescriptor(withTextStyle: style)
// Remove any attributes that specify a font family or name and remove the usage
// This will leave other attributes such as size and weight, etc.
var fontAttrs = defaultFontDescriptor.fontAttributes
fontAttrs.removeValue(forKey: .family)
fontAttrs.removeValue(forKey: .name)
fontAttrs.removeValue(forKey: .init(rawValue: "NSCTFontUIUsageAttribute"))
let monospacedFontDescriptor = monoDescriptor.addingAttributes(fontAttrs)
return monospacedFontDescriptor.withSymbolicTraits(defaultFontDescriptor.symbolicTraits) ?? monospacedFontDescriptor
}
}
请注意关于您是需要完全等宽字体还是只有等宽数字的字体的评论。 Comment/Uncomment 满足您特定需求的那些行。
示例用法:
let bodyMonospacedFont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: .body), size: 0)
textview.font = bodyMonospacedFont
以下是一些测试代码,用于确认 preferredMonoFontDescriptor(withTextStyle:)
的结果适用于所有样式:
let textStyles: [UIFontTextStyle] = [ .body, .callout, .caption1, .caption2, .footnote, .headline, .subheadline, .largeTitle, .title1, .title2, .title3 ]
for style in textStyles {
let nfont = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: style), size: 0)
let mfont = UIFont(descriptor: .preferredMonoFontDescriptor(withTextStyle: style), size: 0)
print(style)
print(nfont)
print(mfont)
}
如果比较每对结果,它们的大小、粗细和样式都相同,只是字体不同。