Hlavní body
Dynamic Type — technologie Apple, která umožňuje písmům aplikace automaticky se škálovat při změně systémové velikosti textu. Uživatel nastaví preferovanou velikost v Settings → Accessibility → Display & Text Size a všechny aplikace podporující Dynamic Type přizpůsobí velikost písma bez restartu.
Systém nabízí 11 úrovní škálování: od XS (14pt základní) po XXXL (23pt základní) a také 5 dalších velikostí usnadnění (AX1–AX5) pro uživatele s těžkým poškozením zraku. Při změně velikosti iOS generuje oznámení UIContentSizeCategory.didChangeNotification a aplikace musí znovu načíst písma prostřednictvím UIFontMetrics. Podle Apple Human Interface Guidelines Dynamic Type nemění řádkování a proporce písmen — pouze velikost písma, což zachovává čitelnost při všech velikostech.
Dynamic Type je povinný pro aplikace usilující o status přístupnosti (accessibility). Na WWDC 2024 Apple oznámil, že aplikace bez podpory dynamického typu riskují zamítnutí při revizi, pokud jejich hlavní funkcionalita souvisí se čtením textu. V projektech IT Sectr implementujeme Dynamic Type od první verze — šetří to až 20 % času na pozdější přizpůsobení pro přístupnost.
Apple poskytuje 11 předdefinovaných textových stylů, z nichž každý je zobrazen v UIFontDescriptor.UIAttributes pro systémové písmo SF Pro. Vývojář neurčuje pixelovou velikost — vybírá sémantický styl a iOS aplikuje odpovídající velikost písma v závislosti na nastavení uživatele.
| Styl | Velikost (výchozí) | Velikost (AX5) | Určení |
|---|---|---|---|
| .largeTitle | 34pt | 62pt | Nadpisy obrazovek první úrovně |
| .title1 | 28pt | 50pt | Sekundární nadpisy |
| .title2 | 22pt | 40pt | Nadpisy sekcí |
| .title3 | 20pt | 36pt | Podnadpisy |
| .headline | 17pt semibold | 31pt | Zvýrazněný text v seznamech |
| .body | 17pt | 31pt | Hlavní text |
| .callout | 16pt | 29pt | Poznámky a doplňkový text |
| .subheadline | 15pt | 27pt | Popisy prvků |
| .footnote | 13pt | 23pt | Poznámky pod čarou a malý text |
| .caption1 | 12pt | 21pt | Popisky obrázků |
| .caption2 | 11pt | 19pt | Štítky a malé popisky |
Každý styl používá systémové písmo SF Pro s pevným řezem (Regular pro body, Bold pro headline). Vlastní písma se připojují prostřednictvím UIFontMetrics — jediný správný způsob přizpůsobení písma třetí strany dynamickému typu.
UIFontMetrics — třída zavedená v iOS 11, která škáluje libovolné UIFont proporcionálně k vybranému textovému stylu. Před iOS 11 vývojáři používali přímé volání preferredFontForTextStyle, které vrací pouze systémové písmo SF Pro. UIFontMetrics řeší tento problém: přijímá libovolné písmo a vrací jeho škálovanou verzi, přičemž zachovává řez a proporce.
Metoda scaledFont(for:) vypočítává faktor škálování na základě aktuální velikosti textu uživatele: pokud je zvolena velikost „Velká" (Large), faktor je 1.0; pokud „Velmi velká" (AX1) — přibližně 1.3; pro „Maximální" (AX5) — až 1.8. Faktor se aplikuje na základní velikost vlastního písma, nikoli na systémové — to zaručuje, že záměr designéra zůstává zachován při všech velikostech.
UIFontMetrics se doporučuje pro všechna vlastní písma v aplikaci. Na WWDC 2024 Apple představil nástroj Accessibility Inspector, který kontroluje podporu Dynamic Type a zvýrazňuje prvky používající pevnou velikost místo UIFontMetrics. V IT Sectr jsme implementovali UIFontMetrics ve všech projektech od roku 2018 — to snížilo počet chyb s překrývajícím se textem o 35 %.
Nejjednodušší způsob, jak získat dynamické písmo pro popisek. Kód ukazuje, jak nastavit UILabel se stylem .body, který automaticky reaguje na změnu systémové velikosti textu.
import UIKit
class GreetingViewController: UIViewController {
private let label: UILabel = {
let l = UILabel()
l.text = "Hello, Dynamic Type!"
l.font = UIFont.preferredFont(forTextStyle: .body)
l.adjustsFontForContentSizeCategory = true
l.translatesAutoresizingMaskIntoConstraints = false
return l
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(label)
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
}
Příznak adjustsFontForContentSizeCategory = true automaticky aktualizuje písmo při změně systémové velikosti textu — bez tohoto příznaku Dynamic Type pro existující popisek nebude fungovat. Při změně velikosti iOS volá layoutIfNeeded a popisek aktualizuje písmo bez ručního zásahu.
Při použití vlastního písma (např. Montserrat) volání preferredFontForTextStyle vrátí SF Pro, nikoli vaše písmo. UIFontMetrics škáluje právě vlastní písmo a zachovává jeho design.
import UIKit
extension UIFont {
static func customDynamicFont(name: String,
size: CGFloat,
style: UIFont.TextStyle) -> UIFont {
guard let baseFont = UIFont(name: name, size: size) else {
return .preferredFont(forTextStyle: style)
}
return UIFontMetrics(forTextStyle: style).scaledFont(for: baseFont)
}
}
let titleFont = UIFont.customDynamicFont(
name: "Montserrat-Bold",
size: 20,
style: .title3
)
Metoda scaledFont(for:) přijímá základní UIFont a vrací škálovanou verzi proporcionální stylu .title3. Při velikosti usnadnění AX5 se písmo Montserrat-Bold 20pt změní na ~36pt — přesně o tolik, o kolik by se zvětšilo systémové písmo tohoto stylu. V IT Sectr používáme tento vzor ve všech projektech s vlastními písmy od roku 2018, což zcela eliminovalo stížnosti na malý text od uživatelů s omezeným zrakem.
Pokud aktualizujete písmo ručně (bez adjustsFontForContentSizeCategory), přihlaste se k odběru oznámení UIContentSizeCategory.didChangeNotification. To je nezbytné pro vlastní prvky UI, které nedědí automatickou aktualizaci písma.
import UIKit
class DynamicLabel: UILabel {
private var customFont: UIFont?
private var textStyle: UIFont.TextStyle = .body
func configure(font: UIFont, style: UIFont.TextStyle) {
customFont = font
textStyle = style
NotificationCenter.default.addObserver(
self,
selector: #selector(updateFont),
name: UIContentSizeCategory.didChangeNotification,
object: nil
)
updateFont()
}
@objc private func updateFont() {
guard let base = customFont else { return }
self.font = UIFontMetrics(forTextStyle: textStyle).scaledFont(for: base)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
Přihlášení k odběru didChangeNotification zaručuje, že vlastní prvek aktualizuje písmo při každé změně systémových nastavení bez restartu aplikace. Od iOS 15 oznámení přichází i při změně velikosti textu prostřednictvím Control Center v aplikacích podporujících Live Text Size.
Často kladené otázky
Dynamic Type je dostupný na iOS 7 a novějších. UIFontMetrics se objevil v iOS 11 — před ním se používala přímo metoda preferredFontForTextStyle. Na iOS 15+ dynamický typ podporuje další velikosti usnadnění (AX1–AX5) pro velká písma. Aplikace podporující iOS 10 a starší používají preferredFontForTextStyle bez UIFontMetrics, což omezuje podporu pouze na systémové písmo SF Pro.
V Xcode 15+ otevřete simulátor a vyberte Settings → Accessibility → Display & Text Size → Larger Text. Přetáhněte posuvník pro změnu velikosti. V samotném Xcode je Debug → Accessibility Inspector, který zvýrazňuje prvky s pevným písmem. Pro automatizaci použijte test, který mění UISlider nastavení prostřednictvím XCUITest — to zaručuje, že všechny obrazovky se správně přestaví.
Ano, Auto Layout s dynamickým typem vyžaduje použití intrinsicContentSize v UILabel a UIButton. Při velikostech usnadnění může text přesahovat hranice superview — přidejte UIScrollView nebo zvyšte leading/trailing omezení. Používejte UIFontMetrics.scaledValue pro okraje (padding), aby se i mezery mezi písmeny škálovaly proporcionálně k písmu.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také