Styl akapitu

Na tej stronie dowiesz się, jak stylizować tekst w akapicie. Aby ustawić styl na poziomie akapitu, możesz skonfigurować parametry takie jak textAlign i lineHeight lub zdefiniować własny ParagraphStyle.

Ustawianie wyrównania tekstu

Parametr textAlign pozwala ustawić wyrównanie tekstu w poziomie w obszarze funkcji kompozycyjnej Text.

Domyślnie Text wybierze naturalne wyrównanie tekstu w zależności od wartości treści:

  • Lewa krawędź kontenera Text w przypadku alfabetów pisanych od lewej do prawej, takich jak łaciński, cyrylica czy hangul
  • Prawa krawędź kontenera Text w przypadku alfabetów pisanych od prawej do lewej, takich jak arabski czy hebrajski

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

słowa,

Jeśli chcesz ręcznie ustawić wyrównanie tekstu elementu kompozycyjnego Text, użyj TextAlign.Start i TextAlign.End zamiast odpowiednio TextAlign.Left i TextAlign.Right, ponieważ są one rozpoznawane jako prawa krawędź elementu kompozycyjnego Text w zależności od preferowanej orientacji tekstu w języku. Na przykład TextAlign.End wyrównuje do prawej strony tekst w języku francuskim, a do lewej – tekst w języku arabskim, natomiast TextAlign.Right wyrównuje do prawej strony niezależnie od używanego alfabetu.

Dodawanie wielu stylów w akapicie

Aby dodać wiele stylów w akapicie, możesz użyć ParagraphStyle w AnnotatedString, który można opatrzyć adnotacjami ze stylami dowolnych adnotacji. Gdy część tekstu zostanie oznaczona tagiem ParagraphStyle, zostanie ona oddzielona od pozostałego tekstu, tak jakby na początku i na końcu znajdowały się znaki końca linii.

Więcej informacji o dodawaniu wielu stylów w tekście znajdziesz w artykule Dodawanie wielu stylów w tekście.

AnnotatedString ma bezpieczny pod względem typów kreator, który ułatwia tworzenie: buildAnnotatedString. Ten fragment kodu używa buildAnnotatedString do ustawienia 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")
       }
    )
}TextSnippets.kt

Trzy akapity w trzech różnych stylach: niebieski, czerwony i pogrubiony oraz zwykły czarny

Dostosowywanie wysokości wiersza i dopełnienia

includeFontPadding to starsza właściwość, która dodaje dodatkowe dopełnienie na podstawie danych czcionki u góry pierwszego wiersza i u dołu ostatniego wiersza tekstu. Począwszy od wersji 2024.01.01 zestawienia komponentów Compose, includeFontPadding jest domyślnie ustawione na false, co sprawia, że domyślny układ tekstu jest bardziej zgodny z typowymi narzędziami do projektowania.

Możliwość konfigurowania lineHeight nie jest nowa – jest dostępna od Androida Q. Możesz skonfigurować lineHeight dla Text za pomocą parametru lineHeight, który rozdziela wysokość wiersza w każdym wierszu tekstu. Następnie możesz użyć nowego elementu LineHeightStyle API, aby dodatkowo skonfigurować wyrównanie tekstu w przestrzeni i usunąć odstępy.

Aby zwiększyć precyzję, możesz dostosować lineHeight, używając jednostki tekstowej „em” (względny rozmiar czcionki) zamiast „sp” (skalowane piksele). Więcej informacji o wybieraniu odpowiedniej jednostki tekstu znajdziesz w artykule TextUnit.

Obraz przedstawiający lineHeight jako pomiar na podstawie linii bezpośrednio nad i pod nim.
Rysunek 1. Użyj opcji Wyrównanie i Przytnij, aby dostosować tekst w zestawie lineHeight i w razie potrzeby przyciąć dodatkowe miejsce.

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
            )
        )
    )
)

Oprócz dostosowywania właściwości lineHeight możesz teraz dodatkowo wyśrodkować i sformatować tekst, korzystając z konfiguracji interfejsu LineHeightStyle API: LineHeightStyle.Alignment i LineHeightStyle.Trim (aby funkcja Trim działała, właściwość includeFontPadding musi być ustawiona na false). Wyrównanie i przycinanie wykorzystują zmierzone odstępy między wierszami tekstu, aby lepiej rozłożyć go we wszystkich wierszach, w tym w pojedynczym wierszu tekstu i górnym wierszu bloku tekstu.

LineHeightStyle.Alignment określa, jak wyrównać wiersz w przestrzeni określonej przez wysokość wiersza. W każdym wierszu możesz wyrównać tekst do góry, do dołu, do środka lub proporcjonalnie. LineHeightStyle.Trim pozwala pozostawić lub usunąć dodatkowe miejsce nad pierwszym wierszem i pod ostatnim wierszem tekstu, które zostało wygenerowane przez ustawienia lineHeight i wyrównania. Poniższe przykłady pokazują, jak wygląda tekst wielowierszowy z różnymi konfiguracjami LineHeightStyle.Trim, gdy wyrównanie jest wyśrodkowane (LineHeightStyle.Alignment.Center).

Obraz przedstawiający LineHeightStyle.Trim.None Obraz przedstawiający LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Obraz pokazujący LineHeightStyle.Trim.FirstLineTop Obraz pokazujący LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Więcej informacji o kontekście tej zmiany, działaniu includeFontPadding w systemie widoków oraz zmianach wprowadzonych w Compose i nowych interfejsach API LineHeightStyle znajdziesz w poście na blogu Fixing Font Padding in Compose Text (Naprawianie dopełnienia czcionki w tekście Compose).

Wstaw podziały wiersza

Interfejs API LineBreak określa kryteria, według których tekst jest dzielony na wiele wierszy. Możesz określić typ podziału wiersza w bloku TextStyle funkcji kompozycyjnej Text. Wstępnie ustawione typy podziału wiersza obejmują:

  • Simple – szybkie, podstawowe dzielenie wierszy. Zalecane w przypadku pól do wprowadzania danych.
  • Heading – podział wiersza z luźniejszymi regułami podziału. Zalecany do krótkich tekstów, takich jak tytuły.
  • Paragraph – wolniejsze, wyższej jakości łamanie wierszy, które poprawia czytelność. Zalecane w przypadku większych ilości tekstu, np. akapitów.

Ten fragment kodu używa zarówno Simple, jak i Paragraph, aby określić zachowanie podziału wiersza w długim bloku tekstu:

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
                )
             )
)TextSnippets.kt

Blok tekstu z prostą strategią podziału wierszy i blok tekstu ze strategią podziału zoptymalizowaną pod kątem akapitów. Blok tekstu z prostą strategią podziału wierszy ma większą zmienność długości wierszy.
Rysunek 1. Blok tekstu z prostą strategią podziału wierszy (góra) i blok tekstu z podziałem wierszy zoptymalizowanym pod kątem akapitu (dół).

W powyższym przykładzie widać, że sposób podziału wierszy w Paragraph daje bardziej zrównoważony wizualnie efekt niż w Simple.

Dostosowywanie podziałów wierszy

Możesz też utworzyć własną konfigurację LineBreak za pomocą parametru Strategy. Strategy może być dowolnym z tych elementów:

  • Balanced – próbuje wyrównać długość wierszy tekstu, stosując też automatyczne dzielenie wyrazów, jeśli jest włączone. Zalecany w przypadku małych ekranów, np. zegarków, aby zmaksymalizować ilość wyświetlanego tekstu.
  • HighQuality – optymalizuje akapit pod kątem bardziej czytelnego tekstu, w tym przenoszenia wyrazów, jeśli jest włączone. (Powinna być domyślna dla wszystkich elementów, które nie są Balanced ani Simple).
  • Simple – podstawowa, szybka strategia. Jeśli ta opcja jest włączona, dzielenie wyrazów jest stosowane tylko w przypadku słów, które nie mieszczą się w całym wierszu. Przydatne podczas edytowania tekstu, aby uniknąć zmiany pozycji podczas pisania.

Poniższy fragment kodu pokazuje różnicę między akapitem z ustawieniami domyślnymi a akapitem zoptymalizowanym pod kątem małych ekranów za pomocą strategii podziału wiersza 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
             )
)TextSnippets.kt

Akapit ze strategią zrównoważonego podziału wierszy i akapit sformatowany bez strategii. Akapit ze strategią zrównoważonego podziału wierszy ma bardziej spójne długości wierszy niż domyślna strategia.
Rysunek 2. Akapit sformatowany ze strategią podziału wierszy Balanced (u góry) i akapit sformatowany bez strategii podziału wierszy.

Uwagi dotyczące języków CJK

Możesz też dostosować LineBreak za pomocą interfejsów API Strictness i WordBreak, które zostały zaprojektowane specjalnie dla języków CJK. Efekty działania tych interfejsów API mogą nie zawsze być widoczne w językach innych niż chiński, japoński i koreański. Ogólnie reguły podziału wierszy są definiowane na podstawie języka.

Strictness opisuje rygorystyczność podziału wiersza za pomocą tych właściwości:

  • Default – domyślne reguły podziału dla danego języka. Może odpowiadać Normal lub Strict.
  • Loose – najmniej restrykcyjne reguły. Odpowiednie w przypadku krótkich wierszy.
  • Normal – najczęstsze reguły podziału wiersza.
  • Strict – najbardziej rygorystyczne reguły podziału wierszy.

WordBreak określa, jak należy wstawiać podziały wierszy w słowach, za pomocą tych właściwości:

  • Default – domyślne reguły podziału dla danego języka.
  • Phrase – podział wiersza jest oparty na wyrażeniach.

Poniższy fragment kodu używa rygorystyczności Strict i ustawienia podziału słów Phrase w przypadku tekstu w języku japońskim:

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 = customTitleLineBrenippets.kt

Tekst w języku japońskim z ustawieniami Strictness i WordBreak w porównaniu z tekstem domyślnym.
Rysunek 3. Tekst sformatowany za pomocą ustawień Strictness i WordBreak (góra) w porównaniu z tekstem sformatowanym tylko za pomocą ustawienia LineBreak.Heading (dół).

Dzielenie wyrazów przenoszonych do następnego wiersza

Interfejs API Hyphens umożliwia dodanie do aplikacji obsługi przenoszenia wyrazów. Przenoszenie wyrazów polega na wstawieniu znaku interpunkcyjnego przypominającego kreskę, aby wskazać, że słowo jest podzielone między wiersze tekstu. Gdy ta opcja jest włączona, między sylabami słowa w odpowiednich miejscach dodawane są łączniki.

Domyślnie dzielenie wyrazów jest wyłączone. Aby włączyć dzielenie wyrazów, dodaj Hyphens.Auto jako parametr w bloku 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
                )
             )
)TextSnippets.kt

Akapit bez włączonego dzielenia wyrazów i akapit z włączonym dzieleniem wyrazów.
  Gdy przenoszenie wyrazów jest włączone, wyraz jest dzielony i przenoszony do następnego wiersza.
Rysunek 4. Akapit bez włączonego dzielenia wyrazów (u góry) i akapit z włączonym dzieleniem wyrazów (u dołu).

Jeśli ta opcja jest włączona, przenoszenie wyrazów następuje tylko w tych warunkach:

  • Słowo nie mieści się w wierszu. Jeśli używasz strategii podziału wiersza Simple, przenoszenie wyrazu następuje tylko wtedy, gdy wiersz jest krótszy niż pojedynczy wyraz.
  • Na urządzeniu jest ustawione odpowiednie ustawienie regionalne, ponieważ odpowiednie dzielenie wyrazów jest określane na podstawie słowników obecnych w systemie.