Styl akapitu

Z tej strony dowiesz się, jak formatować tekst w akapitach. Aby ustawić styl na poziomie akapitu, możesz skonfigurować parametry takie jak textAlignlineHeight lub zdefiniować własny parametr ParagraphStyle.

Ustawianie wyrównania tekstu

Parametr textAlign umożliwia ustawienie wyrównania poziomego tekstu w Text obszarze kompozycyjnym.

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ź Text kontenera 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.dp)
    )
}

Słowa

Jeśli chcesz ręcznie ustawić wyrównanie tekstu w Text komponowalnym, używaj TextAlign.StartTextAlign.End zamiast odpowiednio TextAlign.LeftTextAlign.Right, ponieważ w zależności od preferowanego języka i orientacji tekstu są one wyrównywane do prawej krawędzi Text komponowalnego. Na przykład element TextAlign.End jest wyrównywany do prawej strony w przypadku tekstu w języku francuskim, a do lewej strony w przypadku tekstu w języku arabskim, ale element TextAlign.Right jest wyrównywany 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 elemencie AnnotatedString, który może być opatrzony adnotacjami o dowolnych stylach. Gdy część tekstu zostanie oznaczona symbolem ParagraphStyle, zostanie ona oddzielona od pozostałej części tekstu tak, jakby na początku i na końcu znajdowały się znaki końca wiersza.

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 buildAnnotatedString, który ułatwia tworzenie. Poniższy 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")
            }
        }
    )
}

Trzy akapity w 3 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. Od wersji 2024.01.01 pakietu BOM Compose domyślnie ustawiona jest wartość includeFontPadding, która jest zgodna z false. Dzięki temu domyślny układ tekstu jest bardziej zbliżony do układu w popularnych narzędziach do projektowania.

Możliwość konfigurowania lineHeight nie jest nowością – jest dostępna od Androida Q. Możesz skonfigurować lineHeight dla Text za pomocą parametru lineHeight, który rozkłada wysokość wiersza w każdym wierszu tekstu. Następnie możesz użyć nowego elementu LineHeightStyle API, aby dokładniej skonfigurować wyrównanie tekstu w przestrzeni i usunąć białe znaki.

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

Ilustracja pokazująca wysokość wiersza jako pomiar oparty na wierszach bezpośrednio nad i pod nim.
Rysunek 1. Użyj opcji Wyrównanie i Przytnij, aby dostosować tekst w ustawionym lineHeighti 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 parametru lineHeight możesz teraz dodatkowo wyśrodkować i sformatować tekst za pomocą konfiguracji z interfejsem LineHeightStyle API: LineHeightStyle.AlignmentLineHeightStyle.Trim (aby funkcja przycinania działała, parametr includeFontPadding musi mieć wartość false). Wyrównanie i przycinanie wykorzystują zmierzoną przestrzeń między wierszami tekstu, aby odpowiednio rozłożyć ją na wszystkie wiersze, w tym na pojedynczy wiersz tekstu i górny wiersz bloku tekstu.

LineHeightStyle.Alignment określa sposób wyrównania wiersza w przestrzeni zapewnionej przez wysokość wiersza. W każdym wierszu możesz wyrównać tekst do góry, do dołu, do środka lub proporcjonalnie. LineHeightStyle.Trim umożliwia pozostawienie lub usunięcie dodatkowej przestrzeni nad pierwszym wierszem i pod ostatnim wierszem tekstu wygenerowanego na podstawie dowolnych ustawień 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 Ilustracja przedstawiająca LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Ilustracja pokazująca LineHeightStyle.Trim.FirstLineTop Ilustracja przedstawiająca LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Więcej informacji o kontekście tej zmiany, sposobie działania includeFontPadding w systemie View oraz zmianach wprowadzonych w Compose i nowych interfejsach API LineHeightStyle znajdziesz w poście na blogu Fixing Font Padding in Compose Text.

Wstawianie podziałów wiersza

Interfejs LineBreak API 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 Text. Wstępnie ustawione typy podziału wiersza obejmują:

  • Simple – szybkie, podstawowe łamanie wierszy. Zalecane w przypadku pól wprowadzania tekstu.
  • Heading – podział wiersza z mniej rygorystycznymi regułami podziału. Zalecane w przypadku krótkiego tekstu, np. tytułów.
  • Paragraph – wolniejsze, ale lepsze dzielenie wierszy, które poprawia czytelność; Zalecane w przypadku większych ilości tekstu, np. akapitów.

Poniższy fragment kodu używa obu tagów SimpleParagraph, aby określić zachowanie długiego bloku tekstu w przypadku podziału wiersza:

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

Blok tekstu z prostą strategią podziału wierszy i blok tekstu ze strategią podziału zoptymalizowaną pod kątem akapitu. 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 (u góry) i blok tekstu z podziałem wierszy zoptymalizowanym pod kątem akapitu (u dołu).

W powyższych wynikach widać, że podział wierszy w przypadku Paragraph daje bardziej zrównoważony wizualnie rezultat niż podział wierszy w przypadku 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 zrównoważyć długość wierszy tekstu, a także stosuje 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, aby tekst był bardziej czytelny, w tym dzieli wyrazy, jeśli ta funkcja jest włączona. (Powinna to być wartość 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 wyrazów, które nie mieszczą się w jednym 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 Balancedpodziału wierszy:

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

Akapit ze strategią zrównoważonego podziału wierszy i akapit sformatowany bez strategii. W przypadku akapitu ze strategią zrównoważonego podziału wierszy długość wierszy jest bardziej spójna niż w przypadku domyślnej strategii.
Rysunek 2. Akapit sformatowany za pomocą Balancedstrategii podziału wierszy
(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 StrictnessWordBreak, które zostały zaprojektowane specjalnie z myślą o językach CJK. W przypadku języków innych niż CJK efekty działania tych interfejsów API nie zawsze są widoczne. Ogólnie rzecz biorąc, reguły podziału wiersza są definiowane na podstawie ustawień regionalnych.

Strictness określa stopień rygoru podziału wiersza za pomocą tych właściwości:

  • Default – domyślne reguły podziału w przypadku danego ustawienia regionalnego. Może odpowiadać wartości Normal lub Strict.
  • Loose – najmniej restrykcyjne zasady. Odpowiednie w przypadku krótkich linii.
  • Normal – najczęstsze reguły podziału wiersza;
  • Strict – najbardziej rygorystyczne reguły podziału wiersza.

WordBreak określa sposób wstawiania podziałów wiersza w słowach za pomocą tych właściwości:

  • Default – domyślne reguły podziału w przypadku danego ustawienia regionalnego.
  • Phrase – podział wiersza jest oparty na frazach.

Ten fragment kodu używa ustawień Strictstrictness i Phraseword breaking 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 = customTitleLineBreak
    )
)

Tekst w języku japońskim z ustawieniami „Ścisłość” i „Podział słów” w porównaniu z tekstem domyślnym.
Rysunek 3. Tekst sformatowany za pomocą ustawień StrictnessWordBreak (u góry) w porównaniu z tekstem sformatowanym tylko za pomocą ustawienia LineBreak.Heading (u dołu).

Dzielenie wyrazów przenoszonych do następnego wiersza

Interfejs Hyphens API umożliwia dodanie do aplikacji obsługi dzielenia wyrazów. Dzielenie wyrazów polega na wstawianiu znaku interpunkcyjnego podobnego do łącznika, aby wskazać, że wyraz jest podzielony na kilka wierszy tekstu. Gdy ta opcja jest włączona, łączniki są dodawane między sylabami słowa w odpowiednich miejscach.

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

Akapit bez włączonego dzielenia wyrazów i akapit z włączonym dzieleniem wyrazów.
  Gdy dzielenie wyrazów jest włączone, wyraz jest dzielony i rozbijany na 2 linie.
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, dzielenie wyrazów następuje tylko w tych przypadkach:

  • Słowo nie mieści się w wierszu. Jeśli używasz Simplestrategii podziału wiersza, wyraz jest dzielony tylko wtedy, gdy wiersz jest krótszy niż pojedynczy wyraz.
  • Na urządzeniu jest ustawiony odpowiedni język, ponieważ odpowiednie dzielenie wyrazów jest określane na podstawie słowników znajdujących się w systemie.