Created
May 18, 2018 22:51
-
-
Save surpher/b73529c9b2176b74dd8be49799633fd9 to your computer and use it in GitHub Desktop.
Dynamic Type with Custom Font automatically applied on a subclassed UILabel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// With info gathered at https://stackoverflow.com/a/42235227/789720 | |
import UIKit | |
// MARK: - Use | |
// set label to be of class MJLabel programmatically or in storyboards | |
// set the label to be of preferred dynamic type Title 1|Title 2|...|body|... | |
// MARK: - "Global" settings | |
struct MJBranding { | |
static let fontFamily: String = "Party LET" | |
} | |
// MARK: - UILabel | |
class MJLabel: UILabel { | |
required init(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder)! | |
self.commonInit() | |
} | |
override init(frame: CGRect) { | |
super.init(frame: frame) | |
self.commonInit() | |
} | |
fileprivate func commonInit() { | |
let textStyle = self.font.fontDescriptor.object(forKey: UIFontDescriptor.AttributeName.textStyle) as? UIFontTextStyle ?? UIFontTextStyle.body | |
self.font = UIFont.preferredCustomFont(forTextStyle: textStyle) | |
} | |
} | |
// MARK: - UIFont extension | |
extension UIFont { | |
private struct CustomFont { | |
static var fontFamily = MJBranding.fontFamily | |
} | |
/// 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: [ | |
UIFontDescriptor.AttributeName.family: CustomFont.fontFamily, | |
UIFontDescriptor.AttributeName.size: 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) | |
} | |
} | |
// MARK: - UIFontDescriptor | |
extension UIFontDescriptor { | |
private struct SubStruct { | |
static var preferredFontName: String = MJBranding.fontFamily | |
} | |
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, | |
.extraExtraExtraLarge: 23, | |
.extraExtraLarge: 21, | |
.extraLarge: 19, | |
.large: 17, | |
.medium: 16, | |
.small: 15, | |
.extraSmall: 14 | |
], | |
.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, | |
.medium: 11, | |
.small: 11, | |
.extraSmall: 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]!) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment