Skip to content

Instantly share code, notes, and snippets.

@surpher
Created May 18, 2018 22:51
Show Gist options
  • Save surpher/b73529c9b2176b74dd8be49799633fd9 to your computer and use it in GitHub Desktop.
Save surpher/b73529c9b2176b74dd8be49799633fd9 to your computer and use it in GitHub Desktop.
Dynamic Type with Custom Font automatically applied on a subclassed UILabel
// 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