Dynamic Type è una funzione integrata di iOS che modifica automaticamente la dimensione del carattere nell’app in base alle impostazioni di sistema dell’utente. L’utente imposta la dimensione del testo preferita in Impostazioni → Schermo e luminosità → Dimensione testo, e tutte le app che supportano Dynamic Type si adattano senza azioni aggiuntive. Secondo le Linee guida per l’interfaccia umana di Apple, 2024, il supporto di Dynamic Type è un requisito obbligatorio per la pubblicazione sull’App Store, poiché è un elemento fondamentale dell’accessibilità sulla piattaforma iOS.
Punti chiave
Dynamic Type è una tecnologia iOS introdotta in iOS 7 che consente al testo in un’app di adattarsi automaticamente alle impostazioni di dimensione del carattere del sistema. L’utente può aumentare o diminuire il carattere in tutte le app contemporaneamente — senza dover modificare le impostazioni all’interno di ogni singola app.
Secondo Apple WWDC 2023, “Make Your App Visually Accessible”, oltre il 40% degli utenti iOS modifica la dimensione del carattere rispetto a quella predefinita. Per la fascia d’età 65+ anni, questa cifra raggiunge il 70%. Dynamic Type è un requisito obbligatorio per la certificazione di accessibilità dell’App Store. La mancanza di supporto è motivo di rifiuto durante la revisione.
Come funziona: l’app utilizza UIFont.preferredFont(forTextStyle:) invece di UIFont(name:size:). iOS restituisce automaticamente un font ridimensionato in base all’impostazione corrente di sistema. Quando la dimensione cambia nelle impostazioni, iOS genera una notifica UIContentSizeCategory.didChangeNotification — l’app deve ricalcolare il layout.
Dynamic Type è apparso in iOS 7 insieme al design piatto. iOS 10 ha aggiunto il supporto per i font personalizzati tramite UIFontMetrics. iOS 11 ha introdotto i livelli di accessibilità (fino a AccessibilityXXXL). iOS 15 ha aggiunto Dynamic Type in SwiftUI con supporto automatico. Con ogni rilascio, Apple rafforza i requisiti: a partire da iOS 17, le app senza supporto Dynamic Type ricevono un avviso durante il caricamento su App Store Connect.
iOS fornisce 8 stili di testo, ciascuno con dimensione e spessore predefiniti per l’impostazione standard:
| Stile | Costante | Dimensione (L) | Scopo |
|---|---|---|---|
| Large Title | .largeTitle | 34px | Titolo principale dello schermo |
| Title 1 | .title1 | 28px | Intestazione di sezione |
| Title 2 | .title2 | 22px | Sottotitolo |
| Title 3 | .title3 | 20px | Titolo di card |
| Headline | .headline | 17px (grassetto) | Grassetto per enfasi |
| Body | .body | 17px | Testo principale |
| Callout | .callout | 16px | Testo complementare |
| Caption 1 | .caption1 | 12px | Didascalia dell’immagine |
| Caption 2 | .caption2 | 11px | Didascalia piccola |
| Footnote | .footnote | 13px | Nota a piè di pagina |
Usare lo stile corretto non è solo una questione di “aspetto”. UIFont.TextStyle.body in modalità AccessibilityXXXL può raggiungere 53px. Se un’app utilizza un font fisso di 17px per il body, il testo diventa illeggibile per gli utenti che hanno aumentato la dimensione del carattere.
Dynamic Type non si limita a ridimensionare — preserva la gerarchia visiva. Large Title è sempre più grande di Title 1, che è più grande di Body, indipendentemente dal livello di ridimensionamento. I coefficienti di ridimensionamento differiscono: i titoli vengono ridimensionati in modo più aggressivo rispetto al testo principale, in modo che la gerarchia sia mantenuta anche ai livelli di accessibilità.
iOS supporta 11 livelli di ridimensionamento del testo, suddivisi in due categorie:
La differenza tra XS e AccessibilityXXXL per lo stile body varia da 14px a 53px — quasi 4×. Un layout progettato per 17px si rompe completamente a 53px: il testo fuoriesce, i pulsanti si sovrappongono, le celle collidono.
Verificare la categoria corrente nel codice:
let category = UIApplication.shared.preferredContentSizeCategory
// .extraSmall, .small, .medium, .large, .extraLarge ...
if category.isAccessibilityCategory {
// Abilita layout alternativo
}
La categoria di dimensione del testo è disponibile tramite traitCollection.uiContentSizeCategory. Quando l’impostazione di sistema cambia, iOS chiama traitCollectionDidChange su tutte le UIView. In questo metodo, è necessario aggiornare i font e ricalcolare il layout. SwiftUI lo fa automaticamente — UIKit richiede un abbonamento manuale.
Per UICollectionView, utilizzare UICollectionViewCompositionalLayout — adatta automaticamente il numero di colonne alla larghezza dello schermo e alla dimensione del testo. Ai livelli di accessibilità, passare da un layout a due colonne a una colonna singola in modo che il testo non venga troncato e gli elementi non si sovrappongano. Utilizzare layout condizionale: per larghezza regolare — due colonne, per compatta o accessibilità — una colonna.
Implementazione di base in UIKit — UIFont.preferredFont(forTextStyle:). Questo metodo restituisce un font ridimensionato in base all’impostazione corrente di sistema:
titleLabel.font = UIFont.preferredFont(forTextStyle: .headline)
bodyLabel.font = UIFont.preferredFont(forTextStyle: .body)
Per i font personalizzati, utilizzare UIFontMetrics:
let customFont = UIFont(name: "Montserrat-Regular", size: 16)!
titleLabel.font = UIFontMetrics(forTextStyle: .body)
.scaledFont(for: customFont)
// Monitoraggio dei cambiamenti di dimensione
NotificationCenter.default.addObserver(
self,
selector: #selector(preferredContentSizeChanged),
name: UIContentSizeCategory.didChangeNotification,
object: nil
)
Per UILabel in Interface Builder, basta impostare il font come stile di testo e attivare “Automatically Adjusts Font”. Per i font personalizzati, Interface Builder non supporta UIFontMetrics — solo tramite codice.
UIFontMetrics utilizza la stessa curva di ridimensionamento di preferredFont. È possibile specificare fromTextStyle: .body, .headline, ecc. Ogni stile ha il proprio coefficiente di ridimensionamento. Body si ridimensiona moderatamente, Large Title si ridimensiona in modo aggressivo. Se il tuo font personalizzato è utilizzato per il testo principale, usa .body.
In SwiftUI, il supporto per Dynamic Type è integrato per impostazione predefinita. Tutti i modificatori di sistema (.font(.body), .font(.title)) si ridimensionano automaticamente. Lo sviluppatore non deve chiamare UIFont.preferredFont.
Esempio:
Text("Testo principale")
.font(.body)
.lineLimit(nil)
.minimumScaleFactor(0.5)
Per scale personalizzate, utilizzare DynamicTypeSize:
@Environment(\.dynamicTypeSize) var dynamicTypeSize
var body: some View {
Text("Testo adattivo")
.font(.body)
.padding(dynamicTypeSize <= .large ? 8 : 16)
}
SwiftUI aggiorna automaticamente la vista quando la dimensione del testo di sistema cambia — nessun abbonamento aggiuntivo alle notifiche necessario.
Il modificatore .font(.body) funziona solo per il font di sistema. Per i font personalizzati in SwiftUI, utilizzare Font.custom con UIFontMetrics internamente. A partire da iOS 16, SwiftUI supporta DynamicTypeSize in @Environment, consentendo di adattare padding e layout.
Auto Layout è un prerequisito per il supporto di Dynamic Type. Larghezze e altezze fisse (>=, <=) si rompono alle dimensioni di accessibilità. Utilizzare intrinsicContentSize per UILabel — calcola automaticamente l’altezza per la dimensione del font corrente.
Regole di layout adattivo:
Per testi lunghi (ad esempio, articoli, termini di utilizzo), impostare minimumScaleFactor su UILabel — riduce il testo come ultima risorsa quando Auto Layout non può contenere il contenuto. Un valore di 0.5 significa che il font può ridursi al 50% della dimensione preferita.
Esempio di adattamento del padding in base alla categoria di dimensione:
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)
Troncamento del testo — UILabel con numberOfLines = 1 e larghezza fissa tronca il testo a AccessibilityXL. Soluzione: numberOfLines = 0 e vincolo trailing. Sovrapposizione di elementi — pulsanti con altezza fissa si sovrappongono. Soluzione: UIStackView con spaziatura automatica. Contenuto fuori schermo — ScrollView è obbligatorio per i livelli di accessibilità.
Il Simulatore Xcode consente di modificare la dimensione del testo: nel menu del simulatore, vai su Settings → Accessibility → Display & Text Size → Larger Text. Passa attraverso tutti gli 11 livelli e verifica che il testo non sia troncato, i pulsanti siano accessibili e il layout non si rompa.
Per i test automatizzati, utilizzare l’impostazione contentSizeCategory in XCUIApplication:
func testAccessibilitySizes() {
let app = XCUIApplication()
app.launchArguments += [
"-UIPreferredContentSizeCategoryName",
"UICTContentSizeCategoryAccessibilityXXXL"
]
app.launch()
app.scrollViews.buttons["Invia"].tap()
XCTAssertTrue(app.staticTexts["Modulo inviato"]
.waitForExistence(timeout: 5))
}
XCUITest con diversi launchArguments consente di verificare tutti i livelli di ridimensionamento in CI. Non dimenticare di testare le categorie di accessibilità separatamente — sono quelle che più spesso rompono il layout. Secondo Apple, il 70% dei bug di Dynamic Type viene scoperto specificamente ai livelli di accessibilità, perché gli sviluppatori testano solo le dimensioni standard.
Xcode Accessibility Inspector mostra quali font utilizza l’elemento selezionato — fissi o scalabili. Se l’elemento non risponde alle modifiche della dimensione del testo nel simulatore, viene utilizzato un font fisso. Sostituiscilo con UIFont.preferredFont o UIFontMetrics.
Domande frequenti
È il ridimensionamento automatico del testo in un’app in base alle impostazioni di dimensione del sistema. L’utente modifica la dimensione nelle Impostazioni — tutte le app supportate si adattano senza intervento dello sviluppatore.
No. Per i font personalizzati, utilizzare UIFontMetrics(scaledFont:). Questo metodo ridimensiona qualsiasi font rispetto allo stile di testo specificato, preservando le proporzioni.
11 livelli: 5 standard (XS, S, M, L, XL) e 6 livelli di accessibilità (da AccessibilityXL a AccessibilityXXXXXL). La dimensione del font body può variare da 14px a 53px.
In UIKit tramite UIContentSizeCategory.didChangeNotification. In SwiftUI, utilizzare @Environment(\.dynamicTypeSize) — la vista si aggiorna automaticamente quando cambia l’impostazione di sistema.
Gli utenti con carattere ingrandito vedranno testo troncato, elementi sovrapposti e pulsanti rotti. L’app potrebbe essere rifiutata durante la revisione dell’App Store per violazione dei requisiti di accessibilità.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche