加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在Swift 3 / iOS10中使用Dynamic Type和自定义字体的更好方法

发布时间:2020-12-14 02:28:12 所属栏目:百科 来源:网络整理
导读:我试过两种方法: 方法1: label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)label.adjustsFontForContentSizeCategory = true 即使在“设置”中更改了首选文本大小,文本大小也会自动更改,即使在我返回应用程序之前,这也可以正常工作.
我试过两种方法:

方法1:

label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
label.adjustsFontForContentSizeCategory = true

即使在“设置”中更改了首选文本大小,文本大小也会自动更改,即使在我返回应用程序之前,这也可以正常工作.但它只适用于系统字体(旧金山).

方法2:

要使用自定义字体,我向UIFontDescriptor添加了一个扩展:

//from this answer https://stackoverflow.com/a/35467158/2907715
extension UIFontDescriptor {

    private struct SubStruct {
        static var preferredFontName: String = "Avenir-medium"
    }

    static let fontSizeTable : NSDictionary = [
        UIFontTextStyle.headline: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 23,UIContentSizeCategory.accessibilityExtraExtraLarge: 23,UIContentSizeCategory.accessibilityExtraLarge: 23,UIContentSizeCategory.accessibilityLarge: 23,UIContentSizeCategory.accessibilityMedium: 23,UIContentSizeCategory.extraExtraExtraLarge: 23,UIContentSizeCategory.extraExtraLarge: 21,UIContentSizeCategory.extraLarge: 19,UIContentSizeCategory.large: 17,UIContentSizeCategory.medium: 16,UIContentSizeCategory.small: 15,UIContentSizeCategory.extraSmall: 14
        ],UIFontTextStyle.subheadline: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 21,UIContentSizeCategory.accessibilityExtraExtraLarge: 21,UIContentSizeCategory.accessibilityExtraLarge: 21,UIContentSizeCategory.accessibilityLarge: 21,UIContentSizeCategory.accessibilityMedium: 21,UIContentSizeCategory.extraExtraExtraLarge: 21,UIContentSizeCategory.extraExtraLarge: 19,UIContentSizeCategory.extraLarge: 17,UIContentSizeCategory.large: 15,UIContentSizeCategory.medium: 14,UIContentSizeCategory.small: 13,UIContentSizeCategory.extraSmall: 12
        ],UIFontTextStyle.body: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 53,UIContentSizeCategory.accessibilityExtraExtraLarge: 47,UIContentSizeCategory.accessibilityExtraLarge: 40,UIContentSizeCategory.accessibilityLarge: 33,UIContentSizeCategory.accessibilityMedium: 28,UIFontTextStyle.caption1: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 18,UIContentSizeCategory.accessibilityExtraExtraLarge: 18,UIContentSizeCategory.accessibilityExtraLarge: 18,UIContentSizeCategory.accessibilityLarge: 18,UIContentSizeCategory.accessibilityMedium: 18,UIContentSizeCategory.extraExtraExtraLarge: 18,UIContentSizeCategory.extraExtraLarge: 16,UIContentSizeCategory.extraLarge: 14,UIContentSizeCategory.large: 12,UIContentSizeCategory.medium: 11,UIContentSizeCategory.small: 11,UIContentSizeCategory.extraSmall: 11
        ],UIFontTextStyle.caption2: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 17,UIContentSizeCategory.accessibilityExtraExtraLarge: 17,UIContentSizeCategory.accessibilityExtraLarge: 17,UIContentSizeCategory.accessibilityLarge: 17,UIContentSizeCategory.accessibilityMedium: 17,UIContentSizeCategory.extraExtraExtraLarge: 17,UIContentSizeCategory.extraExtraLarge: 15,UIContentSizeCategory.extraLarge: 13,UIContentSizeCategory.large: 11,UIFontTextStyle.footnote: [
            UIContentSizeCategory.accessibilityExtraExtraExtraLarge: 19,UIContentSizeCategory.accessibilityExtraExtraLarge: 19,UIContentSizeCategory.accessibilityExtraLarge: 19,UIContentSizeCategory.accessibilityLarge: 19,UIContentSizeCategory.accessibilityMedium: 19,UIContentSizeCategory.extraExtraExtraLarge: 19,UIContentSizeCategory.extraExtraLarge: 17,UIContentSizeCategory.extraLarge: 15,UIContentSizeCategory.large: 13,UIContentSizeCategory.medium: 12,UIContentSizeCategory.small: 12,]

    final class func preferredDescriptor(textStyle: String) -> UIFontDescriptor {

        let contentSize = UIApplication.shared.preferredContentSizeCategory
        let style = fontSizeTable[textStyle] as! NSDictionary
        return UIFontDescriptor(name: SubStruct.preferredFontName,size: CGFloat((style[contentSize] as! NSNumber).floatValue))
    }

}

并在viewDidLoad()中:

label.font = UIFont(descriptor: UIFontDescriptor.preferredDescriptor(textStyle: UIFontTextStyle.body.rawValue),size: 0)
NotificationCenter.default.addObserver(self,selector:#selector(self.userChangedTextSize(notification:)),name: NSNotification.Name.UIContentSizeCategoryDidChange,object: nil)

这是userChangedTextSize函数:

func userChangedTextSize(notification: NSNotification) {
    label.font = UIFont(descriptor: UIFontDescriptor.preferredDescriptor(textStyle: UIFontTextStyle.body.rawValue),size: 0)
}

此方法的问题是文本大小在用户返回应用程序之前不会更改,然后用户会看到旧文本大小更改为新大小,这是不理想的.

我可以充分利用这两个世界:自定义字体的大小会在后台自动更改吗?

The problem with this method is that the text size won’t change until the user goes back to the app,and then the user would see the old text size change to the new size,which is not ideal.

我分享你的想法,这可能是一个更好的用户体验,但我想你有点过分思考它.

如果您查看系统提供的应用程序(例如联系人),您将清楚地看到在用户返回应用程序之前不会进行刷新.

顺便说一下,你可以为Swift 3重构一下你的代码:

extension UIFontDescriptor {

    private struct SubStruct {
        static var preferredFontName: String = "Avenir-medium"
    }

    static let fontSizeTable: [UIFontTextStyle: [UIContentSizeCategory: CGFloat]] = [
        .headline: [
            .accessibilityExtraExtraExtraLarge: 23,.accessibilityExtraExtraLarge: 23,.accessibilityExtraLarge: 23,.accessibilityLarge: 23,.accessibilityMedium: 23,.extraExtraExtraLarge: 23,.extraExtraLarge: 21,.extraLarge: 19,.large: 17,.medium: 16,.small: 15,.extraSmall: 14
        ],.subheadline: [
            .accessibilityExtraExtraExtraLarge: 21,.accessibilityExtraExtraLarge: 21,.accessibilityExtraLarge: 21,.accessibilityLarge: 21,.accessibilityMedium: 21,.extraExtraExtraLarge: 21,.extraExtraLarge: 19,.extraLarge: 17,.large: 15,.medium: 14,.small: 13,.extraSmall: 12
        ],.body: [
            .accessibilityExtraExtraExtraLarge: 53,.accessibilityExtraExtraLarge: 47,.accessibilityExtraLarge: 40,.accessibilityLarge: 33,.accessibilityMedium: 28,.caption1: [
            .accessibilityExtraExtraExtraLarge: 18,.accessibilityExtraExtraLarge: 18,.accessibilityExtraLarge: 18,.accessibilityLarge: 18,.accessibilityMedium: 18,.extraExtraExtraLarge: 18,.extraExtraLarge: 16,.extraLarge: 14,.large: 12,.medium: 11,.small: 11,.extraSmall: 11
        ],.caption2: [
            .accessibilityExtraExtraExtraLarge: 17,.accessibilityExtraExtraLarge: 17,.accessibilityExtraLarge: 17,.accessibilityLarge: 17,.accessibilityMedium: 17,.extraExtraExtraLarge: 17,.extraExtraLarge: 15,.extraLarge: 13,.large: 11,.footnote: [
            .accessibilityExtraExtraExtraLarge: 19,.accessibilityExtraExtraLarge: 19,.accessibilityExtraLarge: 19,.accessibilityLarge: 19,.accessibilityMedium: 19,.extraExtraExtraLarge: 19,.extraExtraLarge: 17,.extraLarge: 15,.large: 13,.medium: 12,.small: 12,.extraSmall: 12
        ]
    ]

    final class func preferredDescriptor(textStyle: UIFontTextStyle) -> UIFontDescriptor {
        let contentSize = UIApplication.shared.preferredContentSizeCategory
        let style = fontSizeTable[textStyle]!
        return UIFontDescriptor(name: SubStruct.preferredFontName,size: style[contentSize]!)
    }
}

无需转换为NSDictionary或NSNumber并间接获取floatValue.

这样,您的呼叫站点可以使用以下更易读的代码:

func userChangedTextSize(notification: NSNotification) {
    label.font = UIFont(descriptor: .preferredDescriptor(textStyle: .body),size: 0)

}

编辑:当我正在进行同样的工作时,我将上述(在常见的解决方案中)改进为更容易的方式.

import UIKIt

extension UIFont {

    private struct CustomFont {
        static var fontFamily = "Avenir"
    }

    /// Returns a bold version of `self`
    public var bolded: UIFont {
        return fontDescriptor.withSymbolicTraits(.traitBold)
            .map { UIFont(descriptor: $0,size: 0) } ?? self
    }

    /// Returns an italic version of `self`
    public var italicized: UIFont {
        return fontDescriptor.withSymbolicTraits(.traitItalic)
            .map { UIFont(descriptor: $0,size: 0) } ?? self
    }

    /// Returns a scaled version of `self`
    func scaled(scaleFactor: CGFloat) -> UIFont {
        let newDescriptor = fontDescriptor.withSize(fontDescriptor.pointSize * scaleFactor)
        return UIFont(descriptor: newDescriptor,size: 0)
    }

    class func preferredCustomFont(forTextStyle textStyle: UIFontTextStyle) -> UIFont {
        // we are using the UIFontDescriptor which is less expensive than creating an intermediate UIFont
        let systemFontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: textStyle)

        let customFontDescriptor = UIFontDescriptor.init(fontAttributes: [
            UIFontDescriptorFamilyAttribute: CustomFont.fontFamily,UIFontDescriptorSizeAttribute: systemFontDescriptor.pointSize // use the font size of the default dynamic font
        ])

        // return font of new family with same size as the preferred system font
        return UIFont(descriptor: customFontDescriptor,size: 0)
    }

}

用法

func userChangedTextSize(notification: NSNotification) {
    label.font = UIFont.preferredCustomFont(forTextStyle: .headline)
    // or in Bold / Italic:
    // label.font = UIFont.preferredCustomFont(forTextStyle: .headline).bolded
    // label.font = UIFont.preferredCustomFont(forTextStyle: .headline).italicized
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读