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 komponencie, używaj TextAlign.StartTextAlign.End zamiast odpowiednio TextAlign.LeftTextAlign.Right, ponieważ są one wyrównywane do prawej krawędzi Text komponentu w zależności od preferowanego kierunku tekstu w danym języku. Na przykład element TextAlign.End jest wyrównywany do prawej strony w przypadku tekstu w języku francuskim i 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ć do akapitu wiele stylów, możesz użyć ParagraphStyleAnnotatedString, 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 o czcionce u góry pierwszego wiersza i u dołu ostatniego wiersza tekstu. Od wersji 2024.01.01 BOM Compose includeFontPadding jest domyślnie ustawiona na false, co sprawia, że domyślny układ tekstu jest bardziej zgodny z popularnymi narzędziami 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 lineHeight, i w razie potrzeby przytnij 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 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łu, ś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 Obraz przedstawiający LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Ilustracja przedstawiają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 widoków oraz zmianach wprowadzonych w Compose i nowych interfejsach API LineHeightStyle znajdziesz w poście na blogu Fixing Font Padding in Compose Text (Poprawianie dopełnienia czcionki w tekście Compose).

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ótkich tekstów, takich jak tytuły.
  • Paragraph – wolniejsze, ale lepsze dzielenie wierszy, które poprawia czytelność; Zalecane w przypadku większych ilości tekstu, np. akapitów.

W tym fragmencie kodu użyto obu tagów – SimpleParagraph – do określenia sposobu podziału długiego bloku tekstu na wiersze:

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ł wiersza Paragraph daje bardziej zrównoważony wizualnie rezultat niż podział 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 myślnikiem, jeśli ta funkcja jest włączona. (Powinno być domyślnym ustawieniem 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
            )
        }
    )
)

A paragraph with a balanced line breaking strategy and a paragraph
  formatted without a strategy. 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 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ń ścisłości 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 wierszy.
  • 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ń StrictścisłościPhrasePhrasepodziału słówPhrase 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, w odpowiednich miejscach między sylabami słowa dodawane są łączniki.

Domyślnie dzielenie wyrazów nie jest włą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 dwie linie.
Rysunek 4. Akapit bez włączonego dzielenia wyrazów (u góry) i akapit z włączonym dzieleniem wyrazów (u dołu).

Po włączeniu 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.