Користувач із порушенням зору відкриває ваш додаток і через Onboarding не може прочитати текст — шрифт занадто дрібний. Він іде в Налаштування, вмикає Larger Text на максимум, повертається — а текст той самий. Це не гіпотеза: до 30% користувачів iOS збільшують шрифт. Dynamic Type — системний механізм, що дозволяє підлаштувати розмір тексту під уподобання. Якщо його немає, ви втрачаєте аудиторію та ризикуєте потрапити під Section 4.2 App Store Review Guidelines.
Ми — мобільні розробники з 10+ роками досвіду в iOS (Swift 5.9+, SwiftUI, UIKit). За 5 років ми впровадили Dynamic Type у 40+ проєктах — від fintech до edtech. Отримайте консультацію та аудит доступності вашого додатка.
Чому Dynamic Type важливий для доступності?
Згідно з Apple Human Interface Guidelines, Dynamic Type — обов'язковий елемент доступності. Без нього користувачі з порушеннями зору не можуть комфортно читати контент. Статистика: близько 30% користувачів iOS налаштовують розмір шрифту більше стандартного. Ігноруючи Dynamic Type, ви втрачаєте аудиторію. Крім того, це часта причина відмови в публікації в App Store.
Як правильно підключити Dynamic Type
UIKit
UIFont.preferredFont(forTextStyle: .body) — шрифт із підтримкою Dynamic Type із системної таблиці. Автоматично масштабується при зміні налаштування. adjustsFontForContentSizeCategory = true на UILabel, UITextField, UITextView — вмикає реагування на зміну в реальному часі (без рестарту додатка).
Для кастомних шрифтів: UIFontMetrics(forTextStyle: .body).scaledFont(for: customFont). UIFontMetrics масштабує кастомний шрифт пропорційно системній таблиці для вибраного TextStyle.
Часта помилка: задати шрифт через UIFont(name: "CustomFont-Regular", size: 17) без UIFontMetrics — розмір фіксований, Dynamic Type не працює.
SwiftUI
Font.body, Font.headline, Font.caption — системні шрифти з Dynamic Type з коробки. Для кастомних: Font.custom("CustomFont-Regular", size: 17, relativeTo: .body) — параметр relativeTo вмикає масштабування.
@ScaledMetric — для масштабування нешрифтових значень (відступи, іконки):
@ScaledMetric(relativeTo: .body) var iconSize: CGFloat = 24
При AX5 іконка виросте до ~72pt. Це важливо: іконки та відступи повинні масштабуватися разом із текстом, інакше layout розвалюється.
Як уникнути проблем із layout на великих розмірах?
Фіксована висота рядків і контейнерів
UILabel з numberOfLines = 1 і фіксованою висотою — текст обрізається. На AX5 заголовок із 20 символів займає 3 рядки. Рішення: прибрати фіксовані height constraints на текстових елементах, використовувати numberOfLines = 0 де можливо.
Горизонтальні стеки з текстом
UIStackView з axis = .horizontal і двома UILabel — при великому шрифті мітки не поміщаються поруч. Потрібно або перемикати axis на .vertical при великих розмірах через traitCollectionDidChange, або спочатку проєктувати вертикальний layout.
У SwiftUI: ViewThatFits (iOS 16+) — вибирає layout залежно від доступного простору. Для ранніх версій — @Environment(\.sizeCategory) + умовний HStack/VStack.
Таблиці та колекції
UITableViewCell з Auto Layout і без фіксованої висоти — нормально. З tableView.rowHeight = 44 — при AX5 контент не влізе. tableView.rowHeight = UITableView.automaticDimension обов'язковий.
Кнопки з іконкою та текстом
На AX3+ текст може переноситися і кнопка змінює розмір — це може порушити layout сусідніх елементів.
Як тестувати Dynamic Type на всіх розмірах?
Xcode Simulator: міняємо розмір шрифту через Settings прямо в симуляторі. Або через Environment Overrides (Xcode Debug → Simulate Dynamic Type) — зручніше при розробці.
Обов'язково перевіряємо accessibility розміри (AX1-AX5) — багато команд тестують лише стандартний діапазон і пропускають проблеми з екстремальними розмірами.
Snapshot-тести з фіксованими ContentSizeCategory: UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraExtraLarge) — додаємо в CI, щоб layout-регресії ловилися автоматично. Це скорочує час ручного тестування на 80%.
Порівняння UIKit та SwiftUI для Dynamic Type
| Аспект | UIKit | SwiftUI |
|---|---|---|
| Системні шрифти | UIFont.preferredFont(forTextStyle:) |
Font.body, Font.headline |
| Кастомні шрифти | UIFontMetrics.scaledFont(for:) |
Font.custom(_:size:relativeTo:) |
| Масштабування контейнерів | adjustsFontForContentSizeCategory |
Вбудовано за замовчуванням |
| Масштабування нешрифтових | Вручну через contentSizeCategory |
@ScaledMetric |
| Адаптація layout | traitCollectionDidChange |
@Environment(\.sizeCategory) |
Типові проблеми та їх вирішення
Перелічимо часті граблі та як їх обійти. Якщо в UILabel текст обрізається — перевірте numberOfLines і зніміть фіксовану висоту. Кастомний шрифт не масштабується — швидше за все, ви забули UIFontMetrics. Layout розвалюється на AX5 — застосуйте ViewThatFits або динамічну зміну осі стека. Кнопки стають занадто великими — встановіть adjustsFontForContentSizeCategory і використовуйте @ScaledMetric. Проблеми з таблицями — завжди використовуйте automaticDimension.
Що входить у нашу роботу з впровадження Dynamic Type
- Аудит поточного додатка: виявлення місць з фіксованими шрифтами та layout.
- Налаштування текстових стилів: перехід на
preferredFontіUIFontMetrics. - Адаптація constraints: заміна фіксованих висот на автоматичні.
- Створення кастомних компонентів з підтримкою Dynamic Type.
- Тестування на всіх розмірах (xSmall–AX5) вручну та через snapshot-тести.
- Інтеграція в CI/CD: додавання перевірок на регресії layout.
- Документація: опис використаних підходів та політики масштабування.
Приклад з практики
Один із наших клієнтів — фінтех-додаток із сотнями екранів. Після аудиту ми виявили, що 70% екранів використовують фіксовані шрифти. Ми переписали текстові стилі, додали `UIFontMetrics` для кастомних шрифтів і замінили фіксовані висоти на Auto Layout. Результат: додаток коректно відображається на всіх розмірах, включаючи AX5, а час тестування скоротився на 80% завдяки snapshot-тестам.Терміни: від 2 до 5 днів залежно від складності. Вартість розраховується індивідуально на основі обсягу робіт. Зв'яжіться з нами для консультації та отримайте аудит доступності вашого додатка.
Ми гарантуємо, що після впровадження ваш додаток відповідатиме вимогам App Store щодо accessibility, а користувачі з будь-яким зором зможуть комфортно ним користуватися.







