In iOS7 there are new API\'s for getting a font that is automatically adjusted to the text size the user has set in their preferences.
It looks something like this to
This is how I do it in Swift. I like this because it's more general, it only requires one table, and it should work well with any font. First I wrote a generalized multiplier (in a getter).
var fontSizeMultiplier : CGFloat {
get {
switch UIApplication.sharedApplication().preferredContentSizeCategory {
case UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: return 23 / 16
case UIContentSizeCategoryAccessibilityExtraExtraLarge: return 22 / 16
case UIContentSizeCategoryAccessibilityExtraLarge: return 21 / 16
case UIContentSizeCategoryAccessibilityLarge: return 20 / 16
case UIContentSizeCategoryAccessibilityMedium: return 19 / 16
case UIContentSizeCategoryExtraExtraExtraLarge: return 19 / 16
case UIContentSizeCategoryExtraExtraLarge: return 18 / 16
case UIContentSizeCategoryExtraLarge: return 17 / 16
case UIContentSizeCategoryLarge: return 1.0
case UIContentSizeCategoryMedium: return 15 / 16
case UIContentSizeCategorySmall: return 14 / 16
case UIContentSizeCategoryExtraSmall: return 13 / 16
default: return 1.0
}
}
}
Then I update the font (e.g., in the observer) using a UIFontDescriptor
like this:
textView.font = UIFont(descriptor: fontDescriptor!, size: fontDescriptor!.pointSize * fontSizeMultiplier)
In iOS 11 you can use:
var customFont = UIFont.systemFont(ofSize: 17.0)
if #available(iOS 11.0, *) {
customFont = UIFontMetrics.default.scaledFont(for: customFont)
}
// use customFont...
See also Building Apps with Dynamic Type WWDC 2017 - Session 245 - iOS time 8:34.
Swift 2.1-3.0 code based on @smartDonkey's port of @Bob Spryn code. Also updated with the Apple sizes from @Klaas.
import UIKit
extension UIFontDescriptor {
private struct SubStruct {
static var preferredFontName: String = "Roboto-Light"
}
class func preferredDescriptor(textStyle: NSString) -> UIFontDescriptor {
struct Static {
static var onceToken : dispatch_once_t = 0
static var fontSizeTable : NSDictionary = NSDictionary()
}
dispatch_once(&Static.onceToken) {
Static.fontSizeTable = [
UIFontTextStyleHeadline: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 23,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 23,
UIContentSizeCategoryAccessibilityExtraLarge: 23,
UIContentSizeCategoryAccessibilityLarge: 23,
UIContentSizeCategoryAccessibilityMedium: 23,
UIContentSizeCategoryExtraExtraExtraLarge: 23,
UIContentSizeCategoryExtraExtraLarge: 21,
UIContentSizeCategoryExtraLarge: 19,
UIContentSizeCategoryLarge: 17,
UIContentSizeCategoryMedium: 16,
UIContentSizeCategorySmall: 15,
UIContentSizeCategoryExtraSmall: 14
],
UIFontTextStyleSubheadline: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 21,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 21,
UIContentSizeCategoryAccessibilityExtraLarge: 21,
UIContentSizeCategoryAccessibilityLarge: 21,
UIContentSizeCategoryAccessibilityMedium: 21,
UIContentSizeCategoryExtraExtraExtraLarge: 21,
UIContentSizeCategoryExtraExtraLarge: 19,
UIContentSizeCategoryExtraLarge: 17,
UIContentSizeCategoryLarge: 15,
UIContentSizeCategoryMedium: 14,
UIContentSizeCategorySmall: 13,
UIContentSizeCategoryExtraSmall: 12
],
UIFontTextStyleBody: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 53,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 47,
UIContentSizeCategoryAccessibilityExtraLarge: 40,
UIContentSizeCategoryAccessibilityLarge: 33,
UIContentSizeCategoryAccessibilityMedium: 28,
UIContentSizeCategoryExtraExtraExtraLarge: 23,
UIContentSizeCategoryExtraExtraLarge: 21,
UIContentSizeCategoryExtraLarge: 19,
UIContentSizeCategoryLarge: 17,
UIContentSizeCategoryMedium: 16,
UIContentSizeCategorySmall: 15,
UIContentSizeCategoryExtraSmall: 14
],
UIFontTextStyleCaption1: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 18,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 18,
UIContentSizeCategoryAccessibilityExtraLarge: 18,
UIContentSizeCategoryAccessibilityLarge: 18,
UIContentSizeCategoryAccessibilityMedium: 18,
UIContentSizeCategoryExtraExtraExtraLarge: 18,
UIContentSizeCategoryExtraExtraLarge: 16,
UIContentSizeCategoryExtraLarge: 14,
UIContentSizeCategoryLarge: 12,
UIContentSizeCategoryMedium: 11,
UIContentSizeCategorySmall: 11,
UIContentSizeCategoryExtraSmall: 11
],
UIFontTextStyleCaption2: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 17,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 17,
UIContentSizeCategoryAccessibilityExtraLarge: 17,
UIContentSizeCategoryAccessibilityLarge: 17,
UIContentSizeCategoryAccessibilityMedium: 17,
UIContentSizeCategoryExtraExtraExtraLarge: 17,
UIContentSizeCategoryExtraExtraLarge: 15,
UIContentSizeCategoryExtraLarge: 13,
UIContentSizeCategoryLarge: 11,
UIContentSizeCategoryMedium: 11,
UIContentSizeCategorySmall: 11,
UIContentSizeCategoryExtraSmall: 11
],
UIFontTextStyleFootnote: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 19,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 19,
UIContentSizeCategoryAccessibilityExtraLarge: 19,
UIContentSizeCategoryAccessibilityLarge: 19,
UIContentSizeCategoryAccessibilityMedium: 19,
UIContentSizeCategoryExtraExtraExtraLarge: 19,
UIContentSizeCategoryExtraExtraLarge: 17,
UIContentSizeCategoryExtraLarge: 15,
UIContentSizeCategoryLarge: 13,
UIContentSizeCategoryMedium: 12,
UIContentSizeCategorySmall: 12,
UIContentSizeCategoryExtraSmall: 12
],
]
}
let contentSize = UIApplication.sharedApplication().preferredContentSizeCategory
let style = Static.fontSizeTable[textStyle] as! NSDictionary
return UIFontDescriptor(name: SubStruct.preferredFontName, size: CGFloat((style[contentSize] as! NSNumber).floatValue))
}
}
Here is my take on @Gobe's answer, in Swift 3:
extension UIFontDescriptor {
@nonobjc static var fontSizeTable: [UIFontTextStyle : [UIContentSizeCategory : CGFloat]] = {
return [
.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],
]
}()
class func currentPreferredSize(textStyle: UIFontTextStyle = .body) -> CGFloat {
let contentSize = UIApplication.shared.preferredContentSizeCategory
guard let style = fontSizeTable[textStyle], let fontSize = style[contentSize] else { return 17 }
return fontSize
}
class func preferredFontDescriptor(fontName: String = "SnellRoundhand", textStyle: UIFontTextStyle = .body) -> UIFontDescriptor {
return UIFontDescriptor(name: fontName, size: currentPreferredSize())
}
}
@Bob Spryn code rewritten with swift:
import UIKit
extension UIFontDescriptor {
private struct SubStruct {
static var preferredFontName: NSString = "OEMeodedPashutPro-Regular"
}
class func preferredDescriptor(textStyle: NSString) -> UIFontDescriptor {
struct Static {
static var onceToken : dispatch_once_t = 0
static var fontSizeTable : NSDictionary = NSDictionary()
}
dispatch_once(&Static.onceToken) {
Static.fontSizeTable = [
UIFontTextStyleHeadline: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 26,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 25,
UIContentSizeCategoryAccessibilityExtraLarge: 24,
UIContentSizeCategoryAccessibilityLarge: 24,
UIContentSizeCategoryAccessibilityMedium: 23,
UIContentSizeCategoryExtraExtraExtraLarge: 23,
UIContentSizeCategoryExtraExtraLarge: 22,
UIContentSizeCategoryExtraLarge: 21,
UIContentSizeCategoryLarge: 20,
UIContentSizeCategoryMedium: 19,
UIContentSizeCategorySmall: 18,
UIContentSizeCategoryExtraSmall: 17
],
UIFontTextStyleSubheadline: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 24,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 23,
UIContentSizeCategoryAccessibilityExtraLarge: 22,
UIContentSizeCategoryAccessibilityLarge: 22,
UIContentSizeCategoryAccessibilityMedium: 21,
UIContentSizeCategoryExtraExtraExtraLarge: 21,
UIContentSizeCategoryExtraExtraLarge: 20,
UIContentSizeCategoryExtraLarge: 19,
UIContentSizeCategoryLarge: 18,
UIContentSizeCategoryMedium: 17,
UIContentSizeCategorySmall: 16,
UIContentSizeCategoryExtraSmall: 15
],
UIFontTextStyleBody: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 21,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 20,
UIContentSizeCategoryAccessibilityExtraLarge: 19,
UIContentSizeCategoryAccessibilityLarge: 19,
UIContentSizeCategoryAccessibilityMedium: 18,
UIContentSizeCategoryExtraExtraExtraLarge: 18,
UIContentSizeCategoryExtraExtraLarge: 17,
UIContentSizeCategoryExtraLarge: 16,
UIContentSizeCategoryLarge: 15,
UIContentSizeCategoryMedium: 14,
UIContentSizeCategorySmall: 13,
UIContentSizeCategoryExtraSmall: 12
],
UIFontTextStyleCaption1: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 19,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 18,
UIContentSizeCategoryAccessibilityExtraLarge: 17,
UIContentSizeCategoryAccessibilityLarge: 17,
UIContentSizeCategoryAccessibilityMedium: 16,
UIContentSizeCategoryExtraExtraExtraLarge: 16,
UIContentSizeCategoryExtraExtraLarge: 16,
UIContentSizeCategoryExtraLarge: 15,
UIContentSizeCategoryLarge: 14,
UIContentSizeCategoryMedium: 13,
UIContentSizeCategorySmall: 12,
UIContentSizeCategoryExtraSmall: 12
],
UIFontTextStyleCaption2: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 18,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 17,
UIContentSizeCategoryAccessibilityExtraLarge: 16,
UIContentSizeCategoryAccessibilityLarge: 16,
UIContentSizeCategoryAccessibilityMedium: 15,
UIContentSizeCategoryExtraExtraExtraLarge: 15,
UIContentSizeCategoryExtraExtraLarge: 14,
UIContentSizeCategoryExtraLarge: 14,
UIContentSizeCategoryLarge: 13,
UIContentSizeCategoryMedium: 12,
UIContentSizeCategorySmall: 12,
UIContentSizeCategoryExtraSmall: 11
],
UIFontTextStyleFootnote: [
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 16,
UIContentSizeCategoryAccessibilityExtraExtraLarge: 15,
UIContentSizeCategoryAccessibilityExtraLarge: 14,
UIContentSizeCategoryAccessibilityLarge: 14,
UIContentSizeCategoryAccessibilityMedium: 13,
UIContentSizeCategoryExtraExtraExtraLarge: 13,
UIContentSizeCategoryExtraExtraLarge: 12,
UIContentSizeCategoryExtraLarge: 12,
UIContentSizeCategoryLarge: 11,
UIContentSizeCategoryMedium: 11,
UIContentSizeCategorySmall: 10,
UIContentSizeCategoryExtraSmall: 10
],
]
}
let contentSize = UIApplication.sharedApplication().preferredContentSizeCategory
let style = Static.fontSizeTable[textStyle] as NSDictionary
return UIFontDescriptor(name: SubStruct.preferredFontName, size: CGFloat((style[contentSize] as NSNumber).floatValue))
}
}
Usage:
UIFont(descriptor: UIFontDescriptor.preferredDescriptor(UIFontTextStyleBody), size: 0)
In iOS 11 UIFontMetrics
class was introduced. Create a FontMetrics object for the text style that you're interested in. Then choose any font you want, sized for the standard dynamic type size. And then you can ask the FontMetrics object to scale that font given the user's current settings.
let bodyMetrics = UIFontMetrics(forTextStyle: .body)
let standardFont = ... // any font you want, for standard type size
let font = bodyMetrics.scaledFont(for: standardFont)