-
Prepare your tvOS apps for Dynamic Type
Dynamic Type empowers people to comfortably read and interact with your app by letting them choose the text size that works best for them. You'll learn how to get your app ready for Dynamic Type on tvOS through practical techniques for implementing font scaling and adapting your layouts for larger content. You'll also discover how to optimize your media-focused interfaces like grids and carousels, ensuring a great experience for everyone who relies on different text sizes.
Chapters
- 0:01 - Introduction
- 2:46 - Identify common issues
- 6:13 - Adapt your layout
Resources
Related Videos
WWDC24
-
Search this video…
-
-
4:58 - Adopt standard text styles
// Adopt standard text styles VStack(spacing: 20) { Text("Signup information") .font(.caption.bold()) .lineLimit(1) .foregroundStyle(.secondary) .frame(width: 300, alignment: .leading) HStack(alignment: .top, spacing: 40) { //* ... *// } } -
5:10 - Use flexible constraints
// Adopt standard text styles VStack(spacing: 20) { Text("Signup information") .font(.caption.bold()) .lineLimit(1) .foregroundStyle(.secondary) .frame(maxWidth: .infinity, alignment: .leading) HStack(alignment: .top, spacing: 40) { /* ... */ } } -
5:55 - Dynamic Type with text styles in UIKit
// Hard coded text size in UIKit titleLabel.font = UIFont.boldSystemFont(ofSize: 28) // Dynamic Type with text styles in UIKit titleLabel.font = UIFont.preferredFont(forTextStyle: .headline) titleLabel.adjustsFontForContentSizeCategory = true -
7:09 - Adapt layout in response to dynamic type
// A view that shows a collection of movie posters struct MovieShelf: View { @Environment(\.dynamicTypeSize) private var dynamicTypeSize var body: some View { ScrollView(.horizontal) { LazyHStack(spacing: 40) { ForEach(Asset.allCases) { asset in Button { /* ... */ } label: { asset.portraitImage Text(asset.title) } .containerRelativeFrame( .horizontal, count: dynamicTypeSize.isAccessibilitySize ? 4 : 6, spacing: 40) } } } } } -
8:07 - Provide a conditional layout for when larger sizes are turned on
// A view that shows content in a card struct CardContentView: View { @Environment(\.dynamicTypeSize) private var dynamicTypeSize var asset: Asset var body: some View { let layout = dynamicTypeSize.isAccessibilitySize ? AnyLayout(VStackLayout(alignment: .leading, spacing: 10)) : AnyLayout(HStackLayout(alignment: .top, spacing: 10)) layout { /* ... */ } } } -
8:31 - UIKit adaptive layout that responds to content size changes
// UIKit adaptive layout that responds to content size changes class AdaptiveLayoutViewController: UIViewController { let stackView = UIStackView() override func viewDidLoad() { super.viewDidLoad() updateLayout() let sizeTraits: [UITrait] = [UITraitPreferredContentSizeCategory.self] registerForTraitChanges(sizeTraits, action: #selector(updateLayout)) } private func updateLayout() { if traitCollection.preferredContentSizeCategory.isAccessibilityCategory { stackView.axis = .vertical } else { stackView.axis = .horizontal } } }
-
-
- 0:01 - Introduction
Large Text support is now available system-wide on tvOS 27, allowing apps to automatically scale text to match someone's needs and preferences. By supporting Dynamic Type, your app can adapt its layout and display its accessibility support in its Accessibility Nutrition Labels.
- 2:46 - Identify common issues
When accommodating larger text, avoid fixed font sizes and rigid constraints that prevent text from scaling and cause truncation or clipping. Ensure all UI elements are flexible and responsive rather than relying on hardcoded values that break layouts at larger sizes.
- 6:13 - Adapt your layout
Find and replace hardcoded sizes with standard text styles to allow interfaces to grow. In cases where standard scaling isn't enough, adapt your view's layout dynamically—such as reducing the number of columns in a grid—by checking the current `dynamicTypeSize` environment value.