Dynamic Type: concepte cheie, stiluri de text și cum funcționează în iOS

Autor: IT Sectr Publicat: 2026-05-16 Timp de citire: 9 min

Dynamic Type — o funcție încorporată în iOS care modifică automat dimensiunea fontului în aplicație în funcție de setările sistemului utilizatorului. Utilizatorul stabilește dimensiunea preferată a textului în Setări → Ecran și luminozitate → Dimensiune text, iar toate aplicațiile care acceptă Dynamic Type se adaptează fără acțiuni suplimentare. Conform Apple Human Interface Guidelines, 2024, suportul pentru Dynamic Type este o cerință obligatorie pentru publicarea în App Store, deoarece este un element de bază al accesibilității pe platforma iOS.

Elemente esențiale

  • Dynamic Type — mecanismul iOS pentru scalarea automată a textului în funcție de setările sistemului pentru dimensiunea fontului
  • Suportul este asigurat prin stiluri de text (UIFont.TextStyle) — body, headline, caption, title și altele
  • Sistemul acceptă 11 niveluri de scalare de la XSmall la AccessibilityXXXL
  • Pentru fonturile personalizate se folosește metoda UIFontMetrics, care scalează orice font în raport cu stilul body
  • Aspectul trebuie să fie adaptiv — UIStackView, Auto Layout și înălțimea dinamică a celulelor sunt obligatorii

Ce este Dynamic Type în iOS

Dynamic Type — tehnologia iOS, apărută în iOS 7, care permite textului din aplicație să se adapteze automat la setările sistemului pentru dimensiunea fontului. Utilizatorul poate mări sau micșora fontul în toate aplicațiile simultan — fără a fi nevoie să schimbe setările în fiecare aplicație în parte.

Conform Apple WWDC 2023, „Make Your App Visually Accessible”, peste 40% dintre utilizatorii iOS modifică dimensiunea fontului față de cea standard. Pentru grupa de vârstă 65+, acest indicator atinge 70%. Dynamic Type este o cerință obligatorie pentru certificarea de accesibilitate App Store. Absența suportului este un motiv de respingere a aplicației la revizuire.

Principiu de funcționare: aplicația folosește UIFont.preferredFont(forTextStyle:) în loc de UIFont(name:size:). iOS returnează automat fontul scalat în funcție de setarea curentă a sistemului. La modificarea dimensiunii în setări, iOS generează notificarea UIContentSizeCategory.didChangeNotification — aplicația trebuie să recalculeze aspectul.

Istoria dezvoltării Dynamic Type

Dynamic Type a apărut în iOS 7 odată cu designul „plat”. În iOS 10 a fost adăugat suportul pentru fonturi personalizate prin UIFontMetrics. iOS 11 a introdus nivelurile de accesibilitate (până la AccessibilityXXXL). iOS 15 a adăugat Dynamic Type în SwiftUI cu suport automat. Cu fiecare versiune, Apple înăsprește cerințele: începând cu iOS 17, aplicațiile fără suport Dynamic Type primesc un avertisment la încărcarea în App Store Connect.

Stiluri de text UIFont.TextStyle

iOS oferă 8 stiluri de text, fiecare cu o dimensiune și un caracter prestabilit pentru setarea standard:

StilConstantăDimensiune (L)Scop
Large Title.largeTitle34pxTitlul principal al ecranului
Title 1.title128pxTitlul secțiunii
Title 2.title222pxSubtitlu
Title 3.title320pxTitlul cardului
Headline.headline17px (bold)Bold pentru accent
Body.body17pxText principal
Callout.callout16pxText auxiliar
Caption 1.caption112pxLegendă sub imagine
Caption 2.caption211pxLegendă mică
Footnote.footnote13pxNotă de subsol

Folosirea stilului corect nu este doar „aspect vizual”. UIFont.TextStyle.body în modul AccessibilityXXXL poate atinge 53px. Dacă aplicația folosește un font fix de 17px pentru body, textul va deveni ilizibil pentru utilizatorii care au mărit fontul.

Ierarhie vizuală prin stiluri

Dynamic Type nu doar scalează — păstrează ierarhia vizuală. Large Title este întotdeauna mai mare decât Title 1, care este mai mare decât Body, indiferent de nivelul de scalare. Coeficienții de scalare diferă: titlurile se scalează mai activ decât textul principal, pentru ca ierarhia să se păstreze chiar și la nivelurile de accesibilitate.

Niveluri de scalare

iOS acceptă 11 niveluri de scalare a textului, împărțite în două categorii:

  • Dimensiuni standard (5 niveluri): XS, S, M, L (implicit), XL
  • Dimensiuni de accesibilitate (6 niveluri): accessibilityXL, accessibilityXXL, accessibilityXXXL, accessibilityXXXXL, accessibilityXXXXXL, accessibilityXXXXXXL

Diferența între XS și AccessibilityXXXL pentru stilul body este de la 14px la 53px — aproape 4×. Aspectul proiectat pentru 17px se strică complet la 53px: textul iese din limite, butoanele se suprapun, celulele se acoperă reciproc.

Verificați categoria curentă în cod:

swift
let category = UIApplication.shared.preferredContentSizeCategory
// .extraSmall, .small, .medium, .large, .extraLarge ...
if category.isAccessibilityCategory {
    // Activare aspect alternativ
}

traitCollection și dimensiunea textului

Categoria dimensiunii textului este disponibilă prin traitCollection.uiContentSizeCategory. La modificarea setării sistemului, iOS apelează traitCollectionDidChange pe toate UIView-urile. În această metodă trebuie actualizate fonturile și recalculat aspectul. SwiftUI face acest lucru automat — UIKit necesită abonare manuală.

Pentru UICollectionView, folosiți UICollectionViewCompositionalLayout — acesta ajustează automat numărul de coloane în funcție de lățimea ecranului și dimensiunea textului. La nivelurile de accesibilitate, treceți de la aspectul cu două coloane la unul cu o singură coloană, pentru ca textul să nu fie tăiat și elementele să nu se suprapună. Folosiți un aspect condițional: pentru regular width — două coloane, pentru compact sau accessibility — o coloană.

Implementare în UIKit

Implementarea de bază în UIKit — UIFont.preferredFont(forTextStyle:). Această metodă returnează fontul scalat în funcție de setarea curentă a sistemului:

swift
titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
bodyLabel.font = UIFont.preferredFont(forTextStyle: .body)

Pentru fonturi personalizate folosiți UIFontMetrics:

swift
let customFont = UIFont(name: "Montserrat-Regular", size: 16)!
titleLabel.font = UIFontMetrics(forTextStyle: .body)
    .scaledFont(for: customFont)

// Urmărirea modificărilor de dimensiune
NotificationCenter.default.addObserver(
    self,
    selector: #selector(preferredContentSizeChanged),
    name: UIContentSizeCategory.didChangeNotification,
    object: nil
)

Pentru UILabel în Interface Builder, este suficient să setați fontul ca stil de text (Text Style) și să activați „Automatically Adjusts Font”. Pentru fonturile personalizate, IB nu acceptă UIFontMetrics — doar prin cod.

UIFontMetrics și curba de scalare

UIFontMetrics folosește aceeași curbă de scalare ca și preferredFont. Puteți seta fromTextStyle: .body, .headline etc. Fiecare stil are propriul coeficient de scalare. Body se scalează moderat, Large Title — agresiv. Dacă fontul dumneavoastră personalizat este folosit pentru textul principal, utilizați .body.

Dynamic Type în SwiftUI

În SwiftUI, suportul pentru Dynamic Type este încorporat implicit. Toți modificatorii de sistem (.font(.body), .font(.title)) se scalează automat. Dezvoltatorul nu trebuie să apeleze UIFont.preferredFont.

Exemplu:

swift
Text("Text principal")
    .font(.body)
    .lineLimit(nil)
    .minimumScaleFactor(0.5)

Pentru scale personalizate utilizați DynamicTypeSize:

swift
@Environment(\.dynamicTypeSize) var dynamicTypeSize

var body: some View {
    Text("Text adaptiv")
        .font(.body)
        .padding(dynamicTypeSize <= .large ? 8 : 16)
}

SwiftUI actualizează automat vizualizarea la modificarea dimensiunii sistemului de text — fără abonamente suplimentare la notificări.

Limitarea Dynamic Type în SwiftUI

Modificatorul .font(.body) funcționează doar pentru fontul de sistem. Pentru fonturi personalizate în SwiftUI, utilizați Font.custom cu UIFontMetrics sub capotă. începând cu iOS 16, SwiftUI acceptă DynamicTypeSize în @Environment, ceea ce permite adaptarea spațierilor și a aspectului.

Adaptarea aspectului pentru fonturi mari

Auto Layout — condiția obligatorie pentru suportul Dynamic Type. Lățimile și înălțimile fixe (>=, <=) se strică la dimensiunile de accesibilitate. Folosiți intrinsicContentSize pentru UILabel — acesta calculează automat înălțimea în funcție de dimensiunea curentă a fontului.

Reguli pentru aspect adaptiv:

  • UIStackView cu distribution = fill și spacing = >= 8 — elementele vor fi mutate pe rândul următor
  • UITableViewCell cu automaticDimension — înălțimea celulei se adaptează la conținut
  • numberOfLines = 0 pe UILabel — textul nu este tăiat, ci se îndeasă
  • Butoane cu edgeInsets — adăugați spațieri la nivelurile de accesibilitate prin traitCollection.preferredContentSizeCategory

Pentru texte lungi (de exemplu, articole, termeni de utilizare), setați minimumScaleFactor pe UILabel — aceasta micșorează textul ca ultimă soluție atunci când Auto Layout nu poate încăpea conținutul. Valoarea 0.5 înseamnă că fontul se poate micșora până la 50% din dimensiunea preferată.

Exemplu de adaptare a spațierilor la categoria de dimensiune:

swift
let isAccessibility = traitCollection
    .preferredContentSizeCategory.isAccessibilityCategory
stackView.spacing = isAccessibility ? 16 : 8
button.contentEdgeInsets = isAccessibility
    ? UIEdgeInsets(top: 16, left: 24, bottom: 16, right: 24)
    : UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)

Probleme tipice de aspect la nivelurile de accesibilitate

Tăierea textului — UILabel cu numberOfLines = 1 și lățime fixă taie textul la AccessibilityXL. Soluție: numberOfLines = 0 și trailing constraint. Suprapunerea elementelor — butoanele cu înălțime fixă se suprapun. Soluție: UIStackView cu spațiere automată. Ieșirea în afara ecranului — ScrollView este obligatoriu la nivelurile de accesibilitate.

Testarea Dynamic Type

Simulatorul Xcode permite schimbarea dimensiunii textului: în meniul simulatorului Settings → Accessibility → Display & Text Size → Larger Text. Comutați între toate cele 11 niveluri și verificați dacă textul nu este tăiat, butoanele sunt accesibile și aspectul nu este stricat.

Pentru testare automatizată utilizați setarea contentSizeCategory în XCUIApplication:

swift
func testAccessibilitySizes() {
    let app = XCUIApplication()
    app.launchArguments += [
        "-UIPreferredContentSizeCategoryName",
        "UICTContentSizeCategoryAccessibilityXXXL"
    ]
    app.launch()
    app.scrollViews.buttons["Trimite"].tap()
    XCTAssertTrue(app.staticTexts["Formular trimis"]
        .waitForExistence(timeout: 5))
}

XCUITest cu diferite launchArguments permite verificarea tuturor nivelurilor de scalare în CI. Nu uitați să verificați separat categoriile de accesibilitate — ele strică cel mai des aspectul. Conform Apple, 70% dintre erorile Dynamic Type sunt detectate tocmai la nivelurile de accesibilitate, deoarece dezvoltatorii testează doar dimensiunile standard.

Accessibility Inspector: verificarea Dynamic Type

Xcode Accessibility Inspector arată ce fonturi folosește elementul selectat — fix sau scalabil. Dacă elementul nu reacționează la modificarea dimensiunii textului în simulator, înseamnă că se folosește un font fix. Înlocuiți-l cu UIFont.preferredFont sau UIFontMetrics.

Întrebări frecvente

Ce este Dynamic Type în iOS în cuvinte simple?

Este scalarea automată a textului în aplicație în funcție de setările sistemului pentru dimensiune. Utilizatorul schimbă dimensiunea în Setări — toate aplicațiile care acceptă această funcție se adaptează fără implicarea dezvoltatorului.

Dynamic Type funcționează doar cu fonturile de sistem?

Nu. Pentru fonturi personalizate folosiți UIFontMetrics(scaledFont:). Metoda scalează orice font în raport cu stilul de text specificat, păstrând proporțiile.

Câte niveluri de scalare acceptă iOS?

11 niveluri: 5 standard (XS, S, M, L, XL) și 6 niveluri de accesibilitate (de la AccessibilityXL la AccessibilityXXXXXL). Dimensiunea fontului body poate varia de la 14px la 53px.

Cum mă abonez la modificările dimensiunii textului?

În UIKit prin UIContentSizeCategory.didChangeNotification. În SwiftUI folosiți @Environment(\.dynamicTypeSize) — vizualizarea se va actualiza automat la modificarea setării sistemului.

Ce se întâmplă dacă nu accept Dynamic Type?

Utilizatorii cu font mărit vor vedea text tăiat, elemente suprapuse și butoane nefuncționale. Aplicația poate fi respinsă la revizuirea App Store pentru încălcarea cerințelor de accesibilitate.

Concluzii

  • Dynamic Type — mecanismul încorporat iOS pentru scalarea textului în funcție de setările sistemului; obligatoriu pentru App Store
  • Folosiți UIFont.preferredFont(forTextStyle:) pentru fonturile de sistem și UIFontMetrics pentru cele personalizate
  • iOS acceptă 11 niveluri de scalare — de la XS la AccessibilityXXXXXL (14–53px pentru body)
  • În SwiftUI, Dynamic Type funcționează automat prin .font(.body) și @Environment(\.dynamicTypeSize)
  • Aspectul trebuie să fie adaptiv: UIStackView, automaticDimension în tabele, numberOfLines = 0
  • Testați toate cele 11 niveluri, în special categoriile de accesibilitate — 70% dintre aspecte se strică la acestea
  • Abonarea la UIContentSizeCategory.didChangeNotification este obligatorie pentru aplicațiile UIKit

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și