Punti Chiave
Dynamic Type è una tecnologia Apple che consente di ridimensionare automaticamente i caratteri dell'app quando la dimensione del testo di sistema cambia. L'utente imposta la propria dimensione preferita in Impostazioni → Accessibilità → Schermo e Dimensione Testo e tutte le app che supportano Dynamic Type adattano la dimensione del carattere senza riavvio.
Il sistema offre 11 livelli di ridimensionamento: da XS (14pt base) a XXXL (23pt base), più 5 dimensioni di accessibilità aggiuntive (AX1–AX5) per utenti con gravi disabilità visive. Quando la dimensione cambia, iOS genera una notifica UIContentSizeCategory.didChangeNotification e l'app deve ricaricare i caratteri tramite UIFontMetrics. Secondo le Apple Human Interface Guidelines, Dynamic Type non modifica l'interlinea né le proporzioni delle lettere — solo la dimensione del carattere, preservando la leggibilità a tutte le dimensioni.
Dynamic Type è obbligatorio per le app che aspirano allo stato di accessibilità. Al WWDC 2024, Apple ha annunciato che le app senza supporto del tipo dinamico rischiano il rifiuto durante la revisione se la loro funzionalità principale riguarda la lettura del testo. Nei progetti IT Sectr, implementiamo Dynamic Type dalla prima versione — questo fa risparmiare fino al 20% di tempo nel successivo adattamento all'accessibilità.
Apple fornisce 11 stili di testo predefiniti, ciascuno reso tramite UIFontDescriptor.UIAttributes per il carattere di sistema SF Pro. Lo sviluppatore non specifica una dimensione in pixel — sceglie uno stile semantico e iOS applica la dimensione effettiva del carattere in base alle impostazioni dell'utente.
| Stile | Dimensione (default) | Dimensione (AX5) | Utilizzo |
|---|---|---|---|
| .largeTitle | 34pt | 62pt | Titoli schermo di primo livello |
| .title1 | 28pt | 50pt | Titoli secondari |
| .title2 | 22pt | 40pt | Titoli di sezione |
| .title3 | 20pt | 36pt | Sottotitoli |
| .headline | 17pt semibold | 31pt | Testo evidenziato negli elenchi |
| .body | 17pt | 31pt | Testo del corpo |
| .callout | 16pt | 29pt | Callout e testo supplementare |
| .subheadline | 15pt | 27pt | Etichette degli elementi |
| .footnote | 13pt | 23pt | Note a piè di pagina e testo piccolo |
| .caption1 | 12pt | 21pt | Didascalie delle immagini |
| .caption2 | 11pt | 19pt | Etichette e didascalie piccole |
Ogni stile utilizza il carattere di sistema SF Pro con uno spessore fisso (Regular per body, Bold per headline). I caratteri personalizzati vengono collegati tramite UIFontMetrics — l'unico modo corretto per adattare un carattere di terze parti al tipo dinamico.
UIFontMetrics è una classe introdotta in iOS 11 che ridimensiona un UIFont arbitrario proporzionalmente allo stile di testo selezionato. Prima di iOS 11, gli sviluppatori utilizzavano una chiamata diretta a preferredFontForTextStyle, che restituisce solo il carattere di sistema SF Pro. UIFontMetrics risolve questo problema: prende qualsiasi carattere e restituisce la sua versione ridimensionata, preservando spessore e proporzioni.
Il metodo scaledFont(for:) calcola un fattore di ridimensionamento basato sulla dimensione del testo corrente dell'utente: se è selezionato Grande, il fattore è 1.0; se Molto Grande (AX1) — circa 1.3; per Massimo (AX5) — fino a 1.8. Il fattore viene applicato alla dimensione di base del carattere personalizzato, non a quella di sistema — questo garantisce che l'intento del designer sia preservato a tutte le dimensioni.
UIFontMetrics è raccomandato per tutti i caratteri personalizzati in un'app. Al WWDC 2024, Apple ha mostrato lo strumento Accessibility Inspector, che verifica il supporto di Dynamic Type ed evidenzia gli elementi che utilizzano una dimensione del carattere fissa invece di UIFontMetrics. In IT Sectr, abbiamo implementato UIFontMetrics in tutti i progetti dal 2018 — questo ha ridotto i bug di sovrapposizione del testo del 35%.
Il modo più semplice per ottenere un carattere dinamico per un'etichetta. Il codice mostra come impostare un UILabel con lo stile .body che risponde automaticamente alle modifiche della dimensione del testo di sistema.
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),
])
}
}
Il flag adjustsFontForContentSizeCategory = true aggiorna automaticamente il carattere quando la dimensione del testo di sistema cambia — senza questo flag, Dynamic Type non funzionerà per un'etichetta esistente. Quando la dimensione cambia, iOS chiama layoutIfNeeded e l'etichetta aggiorna il carattere senza intervento manuale.
Quando si utilizza un carattere personalizzato (ad esempio Montserrat), chiamare preferredFontForTextStyle restituirà SF Pro, non il tuo carattere. UIFontMetrics ridimensiona specificamente il carattere personalizzato, preservandone il 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
)
Il metodo scaledFont(for:) prende un UIFont di base e restituisce una versione ridimensionata proporzionale allo stile .title3. Alla dimensione di accessibilità AX5, il carattere Montserrat-Bold 20pt diventa ~36pt — esattamente quanto aumenterebbe il carattere di sistema di questo stile. In IT Sectr, abbiamo utilizzato questo modello in tutti i progetti con caratteri personalizzati dal 2018, eliminando completamente i reclami sul testo piccolo da parte degli utenti con disabilità visive.
Se aggiorni manualmente il carattere (senza adjustsFontForContentSizeCategory), sottoscrivi la notifica UIContentSizeCategory.didChangeNotification. Questo è necessario per elementi UI personalizzati che non ereditano l'aggiornamento automatico del carattere.
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)
}
}
La sottoscrizione a didChangeNotification garantisce che l'elemento personalizzato aggiorni il suo carattere ogni volta che le impostazioni di sistema cambiano senza riavviare l'app. Da iOS 15, la notifica arriva anche quando la dimensione del testo viene modificata tramite Centro di Controllo nelle app che supportano Live Text Size.
Domande Frequenti
Dynamic Type è disponibile su iOS 7 e versioni successive. UIFontMetrics è apparso in iOS 11 — prima di allora, il metodo preferredFontForTextStyle veniva utilizzato direttamente. Su iOS 15+, il tipo dinamico supporta dimensioni di accessibilità aggiuntive (AX1–AX5) per caratteri grandi. Le app che supportano iOS 10 e versioni precedenti utilizzano preferredFontForTextStyle senza UIFontMetrics, limitando il supporto al solo carattere di sistema SF Pro.
In Xcode 15+, apri il simulatore e vai su Impostazioni → Accessibilità → Schermo e Dimensione Testo → Testo più grande. Trascina il cursore per modificare la dimensione. In Xcode stesso, c'è Debug → Accessibility Inspector, che evidenzia gli elementi con carattere fisso. Per l'automazione, utilizza un test che modifica il UISlider delle impostazioni tramite XCUITest — questo garantisce che tutti gli schermi si ricostruiscano correttamente.
Sì, Auto Layout con il tipo dinamico richiede l'uso di intrinsicContentSize su UILabel e UIButton. Con dimensioni di accessibilità, il testo potrebbe superare i confini della superview — aggiungi UIScrollView o aumenta i constraint leading/trailing. Usa UIFontMetrics.scaledValue per il padding, in modo che anche la spaziatura tra le lettere venga ridimensionata proporzionalmente al carattere.
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