Главне тачке
Dynamic Type — Apple технологија која омогућава фонтовима апликације да се аутоматски скалирају при промени системске величине текста. Корисник подешава жељену величину у Settings → Accessibility → Display & Text Size, и све апликације које подржавају Dynamic Type прилагођавају величину слова без поновног покретања.
Систем нуди 11 степени скалирања: од XS (14pt основна) до XXXL (23pt основна), као и 5 додатних величина приступачности (AX1–AX5) за кориснике са израженим оштећењима вида. При промени величине, iOS генерише обавештење UIContentSizeCategory.didChangeNotification, и апликација мора поново да учита фонта кроз UIFontMetrics. Према Apple Human Interface Guidelines, Dynamic Type не мења размак између редова и пропорције слова — само величину слова, што чува читљивост на свим величинама.
Dynamic Type је обавезан за апликације које теже статусу приступачних (accessibility). На WWDC 2024, Apple је најавио да апликације без подршке за динамички тип ризикују одбијање при ревизији, ако је њихова основна функционалност везана за читање текста. У пројектима IT Sectr-а, имплементирамо Dynamic Type од прве верзије — то штеди до 20% времена за каснију адаптацију за приступачност.
Apple пружа 11 унапред дефинисаних текстуалних стилова, од којих се сваки приказује у UIFontDescriptor.UIAttributes за системски фонт SF Pro. Програмер не одређује пикселску величину — бира семантички стил, а iOS примењује актуелну величину слова у зависности од подешавања корисника.
| Стил | Величина (подразумевана) | Величина (AX5) | Намена |
|---|---|---|---|
| .largeTitle | 34pt | 62pt | Наслови екрана првог нивоа |
| .title1 | 28pt | 50pt | Секундарни наслови |
| .title2 | 22pt | 40pt | Наслови секција |
| .title3 | 20pt | 36pt | Поднаслови |
| .headline | 17pt semibold | 31pt | Истакнути текст у листама |
| .body | 17pt | 31pt | Основни текст |
| .callout | 16pt | 29pt | Истакнути делови и додатни текст |
| .subheadline | 15pt | 27pt | Описи елемената |
| .footnote | 13pt | 23pt | Фусноте и ситан текст |
| .caption1 | 12pt | 21pt | Описи слика |
| .caption2 | 11pt | 19pt | Ознаке и ситни описи |
Сваки стил користи системски фонт SF Pro са фиксним изгледом (Regular за body, Bold за headline). Прилагођени фонтови се повезују кроз UIFontMetrics — једини исправан начин прилагођавања спољног фонта динамичком типу.
UIFontMetrics — класа уведена у iOS 11, која скалира произвољни UIFont пропорционално изабраном текстуалном стилу. Пре iOS 11, програмери су користили директно позивање preferredFontForTextStyle, које враћа само системски фонт SF Pro. UIFontMetrics решава овај проблем: прихвата било који фонт и враћа његову скалирану верзију, чувајући изглед и пропорције.
Метод scaledFont(for:) израчунава коефицијент скалирања на основу тренутне величине текста корисника: ако је изабрана величина „Велика" (Large), коефицијент је 1.0; ако је „Веома велика" (AX1) — приближно 1.3; за „Максимална" (AX5) — до 1.8. Коефицијент се примењује на основну величину прилагођеног фонта, а не на системски — то гарантује да се дизајнерска замисао чува на свим величинама.
UIFontMetrics се препоручује за све прилагођене фонтове у апликацији. На WWDC 2024, Apple је приказао алатку Accessibility Inspector, која проверава подршку за Dynamic Type и истиче елементе који користе фиксну величину уместо UIFontMetrics. У IT Sectr-у смо имплементирали UIFontMetrics у свим пројектима од 2018. године — то је смањило број грешака са преклапањем текста за 35%.
Најједноставнији начин да се добије динамички фонт за ознаку. Код показује како поставити UILabel са стилом .body, који аутоматски реагује на промену системске величине текста.
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),
])
}
}
Флаг adjustsFontForContentSizeCategory = true аутоматски ажурира фонт при промени системске величине текста — без овог флага Dynamic Type неће радити за постојећу ознаку. При промени величине, iOS позива layoutIfNeeded, и label ажурира фонт без ручне интервенције.
При коришћењу прилагођеног фонта (нпр. Montserrat), позив preferredFontForTextStyle ће вратити SF Pro, а не ваш фонт. UIFontMetrics скалира управо прилагођени фонт, чувајући његов дизајн.
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
)
Метод scaledFont(for:) прихвата основни UIFont и враћа скалирану верзију пропорционалну стилу .title3. При величини приступачности AX5, фонт Montserrat-Bold 20pt се претвара у ~36pt — тачно колико би се повећао системски фонт овог стила. У IT Sectr-у користимо овај образац у свим пројектима са прилагођеним фонтовима од 2018. године, што је потпуно елиминисало жалбе на ситан текст од корисника са оштећењима вида.
Ако ручно ажурирате фонт (без adjustsFontForContentSizeCategory), претплатите се на обавештење UIContentSizeCategory.didChangeNotification. Ово је неопходно за прилагођене UI елементе који не наслеђују аутоматско ажурирање фонта.
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)
}
}
Претплата на didChangeNotification гарантује да ће прилагођени елемент ажурирати фонт при свакој промени системских подешавања без поновног покретања апликације. Од iOS 15, обавештење стиже чак и при промени величине текста кроз Control Center у апликацијама које подржавају Live Text Size.
Често постављана питања
Dynamic Type је доступан на iOS 7 и новијим верзијама. UIFontMetrics се појавио у iOS 11 — пре њега се користио метод preferredFontForTextStyle директно. На iOS 15+ динамички тип подржава додатне величине приступачности (AX1–AX5) за велике фонтове. Апликације које подржавају iOS 10 и старије користе preferredFontForTextStyle без UIFontMetrics, што ограничава подршку само на системски фонт SF Pro.
У Xcode 15+ отворите симулатор и изаберите Settings → Accessibility → Display & Text Size → Larger Text. Превлачите клизач за промену величине. У самом Xcode-у постоји Debug → Accessibility Inspector, који истиче елементе са фиксним фонтом. За аутоматизацију користите тест који мења UISlider подешавања кроз XCUITest — то гарантује да се сви екрани исправно преуређују.
Да, Auto Layout са динамичким типом захтева коришћење intrinsicContentSize у UILabel и UIButton. При величинама приступачности, текст може изаћи из граница superview-а — додајте UIScrollView или повећајте leading/trailing constraints. Користите UIFontMetrics.scaledValue за размаке (padding) како би се и размаци између слова скалирали пропорционално фонту.
Закључци
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође