ios - 如何获得符合辅助功能设置的等宽字体

标签 ios swift fonts ios9 accessibility

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 的扩展,它返回给定文本样式的首选等宽字体描述符。没有使用 UIFontUIFontDescriptor 获得完全等宽字体的简单方法。此解决方案尝试找到一个好的等宽字体,并在需要时回退到 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
    }
}

请注意有关您是需要完全等宽字体还是仅具有等宽数字的字体的注释。注释/取消注释这些行以满足您的特定需求。

示例用法:

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)
}

如果您比较每对结果,它们具有相同的大小、粗细和样式,只是字体不同。

关于ios - 如何获得符合辅助功能设置的等宽字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46642335/

相关文章:

ios - 适用于 flutter ios 上 flutter 的 Firebase Crashlytics 设置

ios - 如何判断一条语句是否需要放在DispatchQueue.main.async中?

ios - 如何快速停止动画返回?

visual-studio - 是否可以诱使 Visual Studio 2008 使用斜体进行注释?

ios - Mobile Safari 自动生成调用电话号码的新元素,这会影响设计

ios - 在 LAN 中广播 UDP 消息以检测 IP 摄像机

ios - 如何恢复 GL_RENDERBUFFER?

ios - 检查用户实际移动的时间

email - 使用 Google 字体进行电子邮件签名

css - Roboto Condensed google 字体在所有浏览器中都会回落