Stile paragrafo

Questa pagina descrive come applicare uno stile al testo del paragrafo. Per impostare lo stile a livello di paragrafo, puoi configurare parametri come textAlign e lineHeight o definire il tuo ParagraphStyle.

Imposta l'allineamento del testo

Il parametro textAlign consente di impostare l'allineamento orizzontale del testo all'interno di un'area di superficie componibile Text.

Per impostazione predefinita, Text selezionerà l'allineamento naturale del testo in base al valore dei contenuti:

  • Bordo sinistro del container Text per alfabeti da sinistra a destra come latino, cirillico o hangul
  • Bordo destro del contenitore Text per alfabeti con scrittura da destra a sinistra, come l'arabo o l'ebraico

@Composable
fun CenterText() {
    Text(
        "Hello World", textAlign = TextAlign.Center, modifier = Modifier.width(150.dp)
    )
}

Le parole

Se vuoi impostare manualmente l'allineamento del testo di un composable Text, preferisci l'utilizzo di TextAlign.Start e TextAlign.End anziché rispettivamente TextAlign.Left e TextAlign.Right, poiché si risolvono sul bordo destro del composable Text a seconda dell'orientamento del testo della lingua preferita. Ad esempio, TextAlign.End si allinea a destra per il testo in francese e a sinistra per il testo in arabo, mentre TextAlign.Right si allinea a destra indipendentemente dall'alfabeto utilizzato.

Aggiungi più stili in un paragrafo

Per aggiungere più stili in un paragrafo, puoi utilizzare ParagraphStyle in un AnnotatedString, che può essere annotato con stili di annotazioni arbitrarie. Una volta contrassegnata una parte del testo con un ParagraphStyle, questa viene separata dal resto del testo come se avesse degli avanzamenti riga all'inizio e alla fine.

Per saperne di più sull'aggiunta di più stili in un testo, consulta Aggiungi più stili nel testo.

AnnotatedString ha un builder con sicurezza dei tipi per semplificare la creazione: buildAnnotatedString. Il seguente snippet utilizza buildAnnotatedString per impostare ParagraphStyle:

@Composable
fun ParagraphStyle() {
    Text(
        buildAnnotatedString {
            withStyle(style = ParagraphStyle(lineHeight = 30.sp)) {
                withStyle(style = SpanStyle(color = Color.Blue)) {
                    append("Hello\n")
                }
                withStyle(
                    style = SpanStyle(
                        fontWeight = FontWeight.Bold, color = Color.Red
                    )
                ) {
                    append("World\n")
                }
                append("Compose")
            }
        }
    )
}

Tre paragrafi in tre stili diversi: blu, rosso e in grassetto e nero normale

Regola l'altezza della riga e la spaziatura interna

includeFontPadding è una proprietà legacy che aggiunge spaziatura interna aggiuntiva in base alle metriche dei caratteri nella parte superiore della prima riga e nella parte inferiore dell'ultima riga di un testo. A partire dalla versione 2024.01.01 della BOM di Compose, includeFontPadding è impostato su false per impostazione predefinita, il che rende il layout di testo predefinito più in linea con gli strumenti di progettazione comuni.

La possibilità di configurare lineHeight non è una novità, è disponibile da Android Q. Puoi configurare lineHeight per Text utilizzando il parametro lineHeight, che distribuisce l'altezza della riga in ogni riga di testo. Puoi quindi utilizzare il nuovo LineHeightStyle API per configurare ulteriormente l'allineamento del testo all'interno dello spazio e rimuovere gli spazi vuoti.

Potresti voler regolare lineHeight utilizzando l'unità di testo "em" (dimensione del carattere relativa) anziché "sp" (pixel scalati) per una maggiore precisione. Per saperne di più sulla selezione di un'unità di testo appropriata, consulta TextUnit.

Immagine che mostra lineHeight come misura basata sulle righe direttamente sopra e sotto.
Figura 1. Utilizza Allineamento e Taglia per regolare il testo all'interno del set lineHeight e tagliare lo spazio aggiuntivo, se necessario.

Text(
    text = text,
    style = LocalTextStyle.current.merge(
        TextStyle(
            lineHeight = 2.5.em,
            platformStyle = PlatformTextStyle(
                includeFontPadding = false
            ),
            lineHeightStyle = LineHeightStyle(
                alignment = LineHeightStyle.Alignment.Center,
                trim = LineHeightStyle.Trim.None
            )
        )
    )
)

Oltre a regolare lineHeight, ora puoi centrare e applicare uno stile al testo utilizzando le configurazioni con l'API LineHeightStyle: LineHeightStyle.Alignment e LineHeightStyle.Trim (includeFontPadding deve essere impostato su false affinché Trim funzioni). Allineamento e Ritaglio utilizzano lo spazio misurato tra le righe di testo per distribuirlo in modo più appropriato su tutte le righe, inclusa una singola riga di testo e la riga superiore di un blocco di testo.

LineHeightStyle.Alignment definisce come allineare la riga nello spazio fornito dall'altezza della riga. All'interno di ogni riga, puoi allineare il testo in alto, in basso, al centro o in modo proporzionale. LineHeightStyle.Trim ti consente quindi di lasciare o rimuovere lo spazio aggiuntivo nella parte superiore della prima riga e nella parte inferiore dell'ultima riga del testo, generato da eventuali modifiche di lineHeight e allineamento. I seguenti esempi mostrano l'aspetto del testo su più righe con varie configurazioni di LineHeightStyle.Trim quando l'allineamento è centrato (LineHeightStyle.Alignment.Center).

Un'immagine che mostra LineHeightStyle.Trim.None Un'immagine che mostra LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Un'immagine che mostra LineHeightStyle.Trim.FirstLineTop Un'immagine che mostra LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Consulta il blog post Fixing Font Padding in Compose Text per saperne di più sul contesto di questa modifica, sul funzionamento di includeFontPadding nel sistema View e sulle modifiche apportate a Compose e alle nuove API LineHeightStyle.

Inserisci interruzioni di riga

L'API LineBreak definisce i criteri in base ai quali il testo viene suddiviso su più righe. Puoi specificare il tipo di interruzione di riga che preferisci nel blocco TextStyle del composable Text. I tipi di interruzione di riga predefiniti includono:

  • Simple: interruzione di riga di base rapida. Consigliata per i campi di immissione di testo.
  • Heading: interruzione di riga con regole di interruzione più flessibili. Consigliato per testi brevi, come i titoli.
  • Paragraph: interruzione di riga più lenta e di qualità superiore per una migliore leggibilità. Opzione consigliata per quantità di testo maggiori, ad esempio paragrafi.

Lo snippet seguente utilizza sia Simple che Paragraph per specificare il comportamento di interruzione di riga su un blocco di testo lungo:

TextSample(
    samples = mapOf(
        "Simple" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Simple
                )
            )
        },
        "Paragraph" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph
                )
            )
        }
    )
)

Un blocco di testo che mostra una semplice strategia di interruzione di riga rispetto a un blocco di testo con una strategia di interruzione ottimizzata per i paragrafi. Il blocco di testo con la strategia di interruzione di riga semplice presenta una maggiore variabilità nella lunghezza delle righe.
Figura 1. Un blocco di testo con una strategia di interruzione di riga semplice (in alto) rispetto a un blocco di testo con interruzione di riga ottimizzata per i paragrafi (in basso).

Nell'output riportato sopra, nota che il comportamento di interruzione di riga Paragraph produce un risultato visivamente più equilibrato rispetto all'interruzione di riga Simple.

Personalizza le interruzioni di riga

Puoi anche creare la tua configurazione LineBreak con il parametro Strategy. Strategy può essere uno dei seguenti:

  • Balanced: tenta di bilanciare la lunghezza delle righe del testo, applicando anche la sillabazione automatica, se abilitata. Consigliato per schermi di piccole dimensioni, come gli smartwatch, per massimizzare la quantità di testo visualizzato.
  • HighQuality: ottimizza un paragrafo per rendere il testo più leggibile, inclusa la sillabazione, se abilitata. (Dovrebbe essere un valore predefinito per tutto ciò che non è Balanced o Simple.)
  • Simple: strategia di base e rapida. Se l'opzione è attiva, la sillabazione viene eseguita solo per le parole che non rientrano in un'intera riga. Utile per modificare il testo per evitare di cambiare posizione durante la digitazione.

Il seguente snippet mostra la differenza tra un paragrafo con impostazioni predefinite e un paragrafo ottimizzato per schermi di piccole dimensioni con la strategia di interruzione di riga Balanced:

TextSample(
    samples = mapOf(
        "Balanced" to {
            val smallScreenAdaptedParagraph =
                LineBreak.Paragraph.copy(strategy = LineBreak.Strategy.Balanced)
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = smallScreenAdaptedParagraph
                )
            )
        },
        "Default" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(200.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default
            )
        }
    )
)

Un paragrafo con una strategia di interruzione di riga bilanciata e un paragrafo formattato senza una strategia. Il paragrafo con la strategia di interruzione di riga bilanciata ha lunghezze di riga più coerenti rispetto a quello predefinito.
Figura 2. Un paragrafo formattato con una strategia di interruzione di riga Balanced (in alto) rispetto a un paragrafo formattato senza una strategia di interruzione di riga.

Considerazioni su CJK

Puoi anche personalizzare LineBreak con le API Strictness e WordBreak, progettate specificamente per le lingue CJK. Potresti non vedere sempre gli effetti di queste API nelle lingue diverse da cinese, giapponese e coreano. In generale, le regole di interruzione di riga vengono definite in base alle impostazioni internazionali.

Strictness descrive la rigidità dell'interruzione di riga con le seguenti proprietà:

  • Default: regole di interruzione predefinite per le impostazioni internazionali. Può corrispondere a Normal o Strict.
  • Loose: le regole meno restrittive. Adatto per righe brevi.
  • Normal: le regole più comuni per l'interruzione di riga.
  • Strict: le regole più rigide per l'interruzione di riga.

WordBreak definisce il modo in cui le interruzioni di riga devono essere inserite all'interno delle parole con le seguenti proprietà:

  • Default: regole di interruzione predefinite per le impostazioni internazionali.
  • Phrase: l'interruzione di riga si basa sulle frasi.

Il seguente snippet utilizza un'impostazione di severità Strict e un'impostazione di interruzione di riga Phrase per un testo in giapponese:

val customTitleLineBreak = LineBreak(
    strategy = LineBreak.Strategy.HighQuality,
    strictness = LineBreak.Strictness.Strict,
    wordBreak = LineBreak.WordBreak.Phrase
)
Text(
    text = "あなたに寄り添う最先端のテクノロジー。",
    modifier = Modifier.width(250.dp),
    fontSize = 14.sp,
    style = TextStyle.Default.copy(
        lineBreak = customTitleLineBreak
    )
)

Testo giapponese con impostazioni di severità e interruzione di riga rispetto al testo predefinito.
Figura 3. Testo formattato con le impostazioni Strictness e WordBreak (in alto) rispetto al testo formattato solo con LineBreak.Heading (in basso).

Sillaba il testo suddiviso su più righe

L'API Hyphens ti consente di aggiungere il supporto della sillabazione alla tua app. La sillabazione consiste nell'inserire un segno di punteggiatura simile a un trattino per indicare che una parola è divisa tra righe di testo. Se questa opzione è attiva, la sillabazione viene aggiunta tra le sillabe di una parola nei punti di sillabazione appropriati.

Per impostazione predefinita, la sillabazione non è abilitata. Per attivare la sillabazione, aggiungi Hyphens.Auto come parametro in un blocco TextStyle:

TextSample(
    samples = mapOf(
        "Hyphens - None" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.None
                )
            )
        },
        "Hyphens - Auto" to {
            Text(
                text = SAMPLE_LONG_TEXT,
                modifier = Modifier
                    .width(130.dp)
                    .border(BorderStroke(1.dp, Color.Gray)),
                fontSize = 14.sp,
                style = TextStyle.Default.copy(
                    lineBreak = LineBreak.Paragraph,
                    hyphens = Hyphens.Auto
                )
            )
        }
    )
)

Un paragrafo senza sillabazione abilitata e un paragrafo con sillabazione abilitata.
  Quando la sillabazione è attiva, una parola viene sillabata e divisa su due righe.
Figura 4. Un paragrafo senza sillabazione attivata (in alto) e un paragrafo con sillabazione attivata (in basso).

Se l'opzione è attiva, la sillabazione avviene solo nelle seguenti condizioni:

  • Una parola non ci sta in una riga. Se utilizzi una strategia di interruzione di riga Simple, la sillabazione di una parola avviene solo se una riga è più corta della singola parola.
  • Sul dispositivo sono impostate le impostazioni internazionali appropriate, poiché la sillabazione corretta viene determinata utilizzando i dizionari presenti nel sistema.