在Swift 3 / iOS10中使用Dynamic Type和自定义字体的更好方法
我试过两种方法:
方法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) } 此方法的问题是文本大小在用户返回应用程序之前不会更改,然后用户会看到旧文本大小更改为新大小,这是不理想的. 我可以充分利用这两个世界:自定义字体的大小会在后台自动更改吗?
我分享你的想法,这可能是一个更好的用户体验,但我想你有点过分思考它. 如果您查看系统提供的应用程序(例如联系人),您将清楚地看到在用户返回应用程序之前不会进行刷新. 顺便说一下,你可以为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 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |