ParagraphStyle è un insieme di parametri di formattazione che definiscono l'aspetto visivo di un paragrafo di testo. Nello sviluppo mobile, ParagraphStyle include allineamento (left, center, right, justified), interlinea, rientro della prima riga, spaziatura tra paragrafi e direzione del testo. Secondo le Material Design Typography Guidelines (2025), l'uso coerente di ParagraphStyle su tutti gli schermi dell'applicazione garantisce un ritmo tipografico uniforme e riduce il rumore visivo durante il passaggio tra le sezioni.
Punti chiave
ParagraphStyle (stile di paragrafo) è un insieme di regole di formattazione applicabili a uno o più paragrafi di testo. A differenza degli stili di carattere (bold, italic, font-size) che agiscono a livello di singoli caratteri, ParagraphStyle gestisce le macro-proprietà: posizionamento del testo nel contenitore, spaziatura tra righe e paragrafi, direzione di scrittura e regole di sillabazione.
Storicamente, il concetto di ParagraphStyle proviene dai sistemi di desktop publishing (QuarkXPress, PageMaker, InDesign), dove ogni paragrafo aveva il proprio insieme di parametri. Nello sviluppo mobile, questo approccio si è trasformato in API software: NSMutableParagraphStyle su iOS, le classi ParagraphStyle e LineBreakStyle in Android, e parametri come textAlign e textHeightBehavior in Flutter. Tutti servono a uno scopo — gestire la formattazione del paragrafo attraverso il codice, senza essere legati a un motore di testo specifico.
Secondo Bringhurst — The Elements of Typographic Style (2024), una corretta configurazione di ParagraphStyle è la base della cultura tipografica dell'interfaccia. Se il carattere tipografico e la dimensione del font definiscono la «voce» del testo, lo stile di paragrafo definisce il suo «respiro»: ritmo, pause e accenti. Nelle interfacce mobili dove lo spazio è limitato, un ParagraphStyle corretto consente di includere più informazioni senza perdere leggibilità.
ParagraphStyle include diversi gruppi di proprietà, ciascuno responsabile di un aspetto specifico della formattazione. Esaminiamo i parametri chiave disponibili nelle API mobili. L'allineamento è il parametro principale che determina la posizione orizzontale del testo. Su iOS è disponibile NSTextAlignment, su Android — Layout.Alignment, in Flutter — TextAlign.
| Proprietà | iOS (NSMutableParagraphStyle) | Android (Compose) | Flutter (TextStyle) |
|---|---|---|---|
| Allineamento | alignment | textAlign | textAlign |
| Rientro sinistro | headIndent | textIndent (in Compose) | — |
| Rientro destro | tailIndent | — | — |
| Rientro prima riga | firstLineHeadIndent | textIndent (firstLine) | — |
| Spaziatura tra paragrafi | paragraphSpacing | paragraphStyle (lineHeight) | — |
| Spaziatura prima del paragrafo | paragraphSpacingBefore | — | — |
| Direzione del testo | baseWritingDirection | TextDirection (Compose) | textDirection |
| Modalità interruzione riga | lineBreakMode | overflow (TextStyle) | overflow (TextStyle) |
È importante capire che non tutte le proprietà sono disponibili su tutte le piattaforme nella stessa misura. Ad esempio, il rientro della prima riga (firstLineHeadIndent) è completamente supportato solo su iOS tramite NSMutableParagraphStyle. In Android, si utilizza SpannableString con LeadingMarginSpan a questo scopo, e in Flutter — RichText con TextSpan personalizzato e padding. Nello sviluppo multipiattaforma (Flutter, React Native), alcune proprietà di ParagraphStyle devono essere emulate tramite contenitori o Spacer.
Su iOS, lo strumento principale per lavorare con lo stile di paragrafo è la classe NSMutableParagraphStyle — una sottoclasse di NSParagraphStyle. Fornisce un set completo di proprietà per gestire la formattazione del paragrafo e viene applicata tramite NSAttributedString. NSMutableParagraphStyle viene utilizzato non solo in UILabel e UITextView, ma anche in Core Text tramite CTParagraphStyle.
// iOS: configurazione completa di ParagraphStyle
let paragraphStyle = NSMutableParagraphStyle()
// Allineamento
paragraphStyle.alignment = .justified // giustificato
// Rientro
paragraphStyle.headIndent = 16 // rientro sinistro
paragraphStyle.tailIndent = -16 // rientro destro (negativo)
paragraphStyle.firstLineHeadIndent = 32 // rientro prima riga
// Spaziatura tra paragrafi
paragraphStyle.paragraphSpacing = 12 // dopo il paragrafo
paragraphStyle.paragraphSpacingBefore = 8 // prima del paragrafo
// Altezza riga
paragraphStyle.minimumLineHeight = 24
paragraphStyle.maximumLineHeight = 24
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.paragraphStyle: paragraphStyle
]
let label = UILabel()
label.attributedText = NSAttributedString(
string: "This paragraph has a custom ParagraphStyle.\n\nSecond paragraph with 12 pt spacing.",
attributes: attributes
)
In SwiftUI non esiste un equivalente diretto di NSMutableParagraphStyle — invece viene utilizzata una combinazione di modificatori: .multilineTextAlignment() per l'allineamento, .lineSpacing() per l'interlinea. Per il rientro della prima riga e la spaziatura tra paragrafi in SwiftUI, è necessario utilizzare Text + padding o AttributedString (disponibile da iOS 15+), che supporta NSParagraphStyle tramite attributi.
// SwiftUI: AttributedString con ParagraphStyle (iOS 15+)
var attributed: AttributedString = """
This is the first paragraph with indent.
This is the second paragraph with 12 pt spacing.
"""
let ps = NSMutableParagraphStyle()
ps.paragraphSpacing = 12
ps.firstLineHeadIndent = 20
let container = AttributeContainer()
.paragraphStyle(ps)
attributed.mergeAttributes(container)
Text(attributed)
.font(.body)
Secondo Apple — Text Programming Guide (2025), NSMutableParagraphStyle supporta fino a 14 diversi parametri di formattazione. È importante ricordare che tailIndent viene impostato come valore negativo rispetto alla larghezza del contenitore, mentre headIndent è positivo. Questo comportamento non ovvio causa spesso errori tra gli sviluppatori iOS principianti.
Su Android, l'approccio a ParagraphStyle differisce tra il sistema View e Jetpack Compose. Nel sistema View classico, i parametri del paragrafo vengono impostati tramite attributi XML di TextView (android:textAlignment, android:lineSpacingExtra) o tramite SpannableString con implementazioni dell'interfaccia ParagraphStyle dal pacchetto android.text.style.
// Sistema Android View: ParagraphStyle tramite SpannableString
val text = "First paragraph with settings.\n\nSecond paragraph."
val spannable = SpannableString(text)
// Allineamento giustificato
spannable.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
0, text.length,
Spannable.SPAN_PARAGRAPH
)
// Rientro prima riga tramite LeadingMarginSpan
spannable.setSpan(
LeadingMarginSpan.Standard(0, 20),
0, text.indexOf('\n'),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
textView.text = spannable
In Jetpack Compose, ParagraphStyle viene gestito tramite parametri di TextStyle. textAlign viene utilizzato per l'allineamento, lineHeight (in sp o em) per l'interlinea, e textIndent per il rientro della prima riga. Compose supporta anche LineBreak per un controllo preciso delle interruzioni di riga (Simple, Heading, Paragraph), particolarmente utile per testo multilingue.
// Jetpack Compose: ParagraphStyle tramite TextStyle
Text(
text = "Primo paragrafo con stile personalizzato.
Secondo paragrafo con rientro.",
style = TextStyle(
textAlign = TextAlign.Justify,
lineHeight = 24.sp,
textIndent = TextIndent(firstLine = 16.sp),
lineBreak = LineBreak.Paragraph
)
)
Secondo Android Developers — Compose ParagraphStyle (2025), quando si utilizza TextIndent in Compose, è importante impostare firstLine in sp (non in dp), poiché il rientro della prima riga deve scalare con il testo. Se il rientro viene impostato in dp, all'aumentare della dimensione del carattere, il rientro della prima riga diventerà visivamente più piccolo, rompendo le proporzioni tipografiche.
In Flutter, il paradigma ParagraphStyle non è separato in una classe dedicata — invece viene utilizzata una combinazione di parametri TextStyle e classi aggiuntive. L'allineamento viene impostato tramite TextAlign, l'interlinea tramite height (senza unità), e TextHeightBehavior controlla i rientri visibili della prima e dell'ultima riga.
// Flutter: ParagraphStyle tramite parametri Text
Text(
'Paragrafo stilizzato in Flutter.
Secondo paragrafo con rientri.',
style: TextStyle(
fontSize: 16,
height: 1.5,
leadingDistribution: TextLeadingDistribution.proportional,
),
textAlign: TextAlign.justify,
textHeightBehavior: TextHeightBehavior(
applyHeightToFirstAscent: true,
applyHeightToLastDescent: true,
),
)
Per scenari più complessi, Flutter offre l'uso di RichText con TextSpan e WidgetSpan personalizzati. Questo consente di combinare testo con widget inline (icone, immagini) in un unico paragrafo, mantenendo regole di formattazione uniformi. Tuttavia, questo approccio richiede il controllo manuale delle interruzioni di riga e non supporta la sillabazione automatica.
// Flutter: RichText con formattazione paragrafo personalizzata
RichText(
text: TextSpan(
style: TextStyle(fontSize: 16, height: 1.5),
children: [
TextSpan(text: 'First paragraph with icon '),
WidgetSpan(
child: Icon(Icons.star, size: 16),
alignment: PlaceholderAlignment.middle,
),
TextSpan(text: '\n\nSecond paragraph after spacing.'),
],
),
)
Secondo Flutter Documentation — Text Widget (2025), TextHeightBehavior è un parametro chiave per la corretta visualizzazione di ParagraphStyle in Flutter. Se applyHeightToFirstAscent è impostato su false, il rientro superiore della prima riga viene ignorato e il testo «si attacca» al bordo superiore del contenitore. Questo è utile per i titoli, ma indesiderabile per il testo principale.
ParagraphStyle deve tenere conto della direzione di scrittura per ogni lingua. Nelle app mobili con supporto per arabo, ebraico o urdu (scrittura da destra a sinistra, RTL), rientri e allineamento devono essere speculari. iOS supporta il passaggio automatico tramite baseWritingDirection = .natural, Android tramite TextDirection, Flutter tramite textDirection.
La configurazione dell'allineamento per le lingue RTL richiede particolare attenzione. Se in modalità LTR headIndent imposta il rientro sinistro, in RTL diventa automaticamente il rientro destro. Tuttavia, non tutte le implementazioni gestiscono correttamente questa transizione quando l'allineamento viene specificato esplicitamente (NSTextAlignment.left invece di NSTextAlignment.natural). Secondo Google Internationalization Guide (2025), per le app multilingue usa sempre l'allineamento naturale e verifica i rientri in entrambe le disposizioni.
// Android: supporto RTL in ParagraphStyle
val textView = TextView(context)
// Abilita supporto RTL automatico
textView.textDirection = View.TEXT_DIRECTION_LOCALE
textView.textAlignment = View.TEXT_ALIGNMENT_TEXT_START
// Spannable con supporto RTL
val spannable = SpannableString(arabicText)
spannable.setSpan(
AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL),
0, arabicText.length,
Spannable.SPAN_PARAGRAPH
)
Le caratteristiche regionali includono anche regole diverse per il rientro della prima riga. Nella tipografia europea, il rientro della prima riga (firstLineHeadIndent) è uno standard per la separazione dei paragrafi. Nella tipografia giapponese e cinese, il rientro della prima riga viene utilizzato anch'esso, ma la sua dimensione può differire (di solito 1 em contro 1,5 em nella tradizione europea). Per la tipografia araba, il rientro della prima riga è raro — i paragrafi sono più spesso separati da spaziatura verticale.
L'errore più comune è utilizzare ParagraphStyle solo tramite attributi globali del campo di testo senza considerare la formattazione diversa dei singoli paragrafi. In un UILabel o TextView con più paragrafi separati da , ParagraphStyle viene applicato uniformemente a tutto il testo, a meno che non si utilizzi testo attribuito con stili diversi per ogni paragrafo.
Secondo UX Collective — Common Typography Bugs in Mobile Apps (2025), i problemi con ParagraphStyle costituiscono il 18% di tutti i bug tipografici nelle applicazioni mobili. I casi più critici sono quando un paragraphSpacing errato porta alla sovrapposizione del testo su righe diverse o quando le lingue RTL vengono visualizzate con rientri LTR. Si consiglia di creare test unitari per ogni parametro di ParagraphStyle con stringhe di test in diverse lingue.
Domande frequenti
NSMutableParagraphStyle gestisce la formattazione del paragrafo (allineamento, rientro, interlinea), mentre TextStyle gestisce gli attributi del carattere (font, colore, dimensione). Entrambi vengono applicati tramite NSAttributedString. ParagraphStyle agisce a livello di paragrafo, TextStyle a livello di carattere. Più istanze di TextStyle possono esistere in un paragrafo, ma solo un ParagraphStyle per paragrafo.
In Jetpack Compose, il rientro della prima riga viene impostato tramite TextIndent all'interno di TextStyle: TextStyle(textIndent = TextIndent(firstLine = 16.sp)). Il valore deve essere in sp per scalare con il testo. Per testo multilinea, il rientro si applica a ogni riga che inizia un nuovo paragrafo (carattere ). Per il primo paragrafo, il rientro viene sempre applicato.
In SwiftUI non esiste un equivalente diretto di paragraphSpacing. Per la spaziatura tra paragrafi, usa AttributedString (iOS 15+) con NSMutableParagraphStyle e la proprietà paragraphSpacing. Oppure separa i paragrafi tramite Text("...\n\n...") e aggiungi .padding() tra i blocchi di testo. Per scenari tipografici complessi, usa NSAttributedString tramite UILabelRepresentable.
TextView in Android non ha una proprietà paragraphSpacing — viene impostata tramite SpannableString con LeadingMarginSpan o tramite un LineBackgroundSpan personalizzato. Per l'interlinea usa setLineSpacing; per la spaziatura tra paragrafi, separa i paragrafi con un aggiuntivo o usa un contenitore composito di più istanze TextView.
Un ParagraphStyle corretto migliora l'accessibilità: una paragraphSpacing sufficiente aiuta gli utenti con disturbi cognitivi a distinguere meglio i confini dei paragrafi. WCAG 2.2 raccomanda la separazione visiva dei paragrafi (rientro o spaziatura). ParagraphSpacing non deve essere inferiore a 1,5 × line-height. Per le lingue RTL, verifica che il rientro sia speculare correttamente.
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