Categories
Swift UIKit

Supporting dynamic type on iOS

Dynamic type is a feature on iOS what allows users to customise size of the text on screen. Supporting dynamic type enables users with low vision condition to still use your app. It defines a set of APIs for getting font sizes matching with users text size choice in the settings. There are two ways of changing the default text size: Settings > Display & Brightness > Text Size and Settings > General > Accessibility > Larger Text. In accessibility settings it is possible to enable larger accessibility sizes what then makes the total count of text size to 12.

Text styles and custom fonts

UIKit defines a list of text styles which are used for getting preferred font for style. Setting the font to a label and turning on adjustsFontForContentSizeCategory on UILabel enables automatic font updates when user changes text size.

extension UIFont.TextStyle {
public static let largeTitle: UIFont.TextStyle
public static let title1: UIFont.TextStyle
public static let title2: UIFont.TextStyle
public static let title3: UIFont.TextStyle
public static let headline: UIFont.TextStyle
public static let subheadline: UIFont.TextStyle
public static let body: UIFont.TextStyle
public static let callout: UIFont.TextStyle
public static let footnote: UIFont.TextStyle
public static let caption1: UIFont.TextStyle
public static let caption2: UIFont.TextStyle
}
let font = UIFont.preferredFont(forTextStyle: style)
// Automatically update font size when user changes preferred text size or accessibility text sizes.
label.adjustsFontForContentSizeCategory = true
label.font = font
// And the same behavior with buttons without attributed title.
button.titleLabel?.adjustsFontForContentSizeCategory = true
button.titleLabel?.font = font

Using custom fonts is not much different, we just need to use UIFontMetrics for getting a scaled font and turning on adjustsFontForContentSizeCategory.

var customFont = UIFont(name: "Futura-medium", size: 15)!
customFont = UIFontMetrics.default.scaledFont(for: customFont)
label.adjustsFontForContentSizeCategory = true
label.font = customFont

Best way for testing text size category changes is to open Accessibility Inspector (Xcode -> Open Developer Tool -> Accessibility Inspector).

Content size categories

Text sizes can grow a lot and therefore in many cases it is needed to adjust the layout based on the current settings. For example, horisontally aligned text fields. In those cases it is easy to use UIStackView and just changing the alignment property based on content size category. Both trait collection and UIApplication implement preferredContentSizeCategory which then can be used for defining the layout. Content size category changes can be observed by observing change notification or trait collection changes.

if traitCollection.preferredContentSizeCategory.isAccessibilityCategory {
// align vertically
}
else {
// align horisontally
}
if traitCollection.preferredContentSizeCategory > .extraLarge {
// align vertically
}
else {
// align horisontally
}

Scaling Images

When text is shown with icons and text size is very large, then it is preferred to scale the icon as well for avoiding awkward looking user interface. Solution here is to provide icon assets as pdf and checking Preserve vector data checkbox in the asset catalog. This allows UIKit to redraw the image in larger sizes when image view’s adjustsImageSizeForAccessibilityContentSizeCategory is enabled.

Summary

Dynamic type is an important feature what enables your app to reach wide range of people. Supporting dynamic text sizes is easy to add although in many cases it requires to adjust the layout direction as well for giving more space for the text.

If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.

Resources

One reply on “Supporting dynamic type on iOS”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s