Как задать стиль абзаца

На этой странице описывается, как можно стилизовать текст для вашего абзац. Чтобы задать стиль на уровне абзаца, можно настроить такие параметры, как textAlign и lineHeight, или определить собственный ParagraphStyle.

Как настроить выравнивание текста

Параметр textAlign позволяет задать горизонтальное выравнивание текста в области Text.

По умолчанию Text выбирает естественное выравнивание текста в зависимости от его содержимого:

  • Левый край контейнера Text для алфавитов с направлением письма слева направо, например латиницы, кириллицы или хангыля.
  • Правый край контейнера Text для языков с направлением письма справа налево, например арабского или иврита.

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

слова

Если вы хотите вручную задать выравнивание текста для composable-функции Text, используйте TextAlign.Start и TextAlign.End вместо TextAlign.Left и TextAlign.Right соответственно. Они выравнивают текст по правому краю composable-функции Text в зависимости от направления текста на выбранном языке. Например, TextAlign.End выравнивает текст на французском языке по правому краю, а на арабском – по левому. При этом TextAlign.Right выравнивает текст по правому краю независимо от используемого алфавита.

Как добавить несколько стилей в абзац

Чтобы добавить несколько стилей в абзац, можно использовать ParagraphStyle в AnnotatedString, который можно аннотировать стилями произвольных аннотаций. После того как часть текста помечена тегом ParagraphStyle, она отделяется от остального текста, как если бы в начале и в конце были переводы строки.

Подробнее о том, как добавить несколько стилей в текст…

В AnnotatedString есть типобезопасный конструктор, который упрощает создание buildAnnotatedString. В следующем фрагменте кода используется buildAnnotatedString, чтобы задать 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

Три абзаца в трех разных стилях: синий, красный полужирный и обычный черный.

Настройка высоты строки и полей

includeFontPadding – это устаревшее свойство, которое добавляет дополнительные отступы на основе метрик шрифта вверху первой строки и внизу последней строки текста. Начиная с версии Compose BOM 2024.01.01, для includeFontPadding по умолчанию задано значение false, что делает макет текста по умолчанию более соответствующим распространенным инструментам дизайна.

Возможность настраивать lineHeight не нова – она доступна с Android Q. Вы можете настроить lineHeight для Text с помощью параметра lineHeight, который распределяет высоту строки в каждой строке текста. Затем вы можете использовать новый LineHeightStyle API, чтобы дополнительно настроить выравнивание этого текста в пространстве и удалить пробелы.

Для большей точности вы можете настроить lineHeight, используя текстовую единицу em (относительный размер шрифта) вместо sp (масштабируемые пиксели). Подробнее о том, как выбрать подходящий текстовый блок, рассказывается в статье TextUnit.

Изображение, показывающее lineHeight как измерение, основанное на линиях непосредственно над и под ним.
Рисунок 1. Используйте функции "Выравнивание" и "Обрезка", чтобы настроить текст в наборе lineHeight и при необходимости обрезать лишнее пространство.

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

Помимо настройки lineHeight, теперь вы можете дополнительно центрировать и стилизовать текст, используя конфигурации с LineHeightStyle API: LineHeightStyle.Alignment и LineHeightStyle.Trim (чтобы обрезка работала, для includeFontPadding должно быть установлено значение false). Выравнивание и обрезка используют измеренное пространство между строками текста, чтобы более правильно распределить его по всем строкам, включая одну строку текста и верхнюю строку блока текста.

LineHeightStyle.Alignment определяет, как выравнивать строку в пространстве, заданном высотой строки. В каждой строке текст можно выровнять по верхнему или нижнему краю, по центру или пропорционально. LineHeightStyle.Trim позволяет оставить или удалить дополнительное пространство вверху первой строки и внизу последней строки текста, созданное в результате корректировки lineHeight и выравнивания. Ниже показано, как выглядит многострочный текст с различными конфигурациями LineHeightStyle.Trim при выравнивании по центру (LineHeightStyle.Alignment.Center).

Изображение, демонстрирующее LineHeightStyle.Trim.None Изображение, демонстрирующее LineHeightStyle.Trim.Both
LineHeightStyle.Trim.None LineHeightStyle.Trim.Both
Изображение, демонстрирующее LineHeightStyle.Trim.FirstLineTop Изображение, демонстрирующее LineHeightStyle.Trim.LastLineBottom
LineHeightStyle.Trim.FirstLineTop LineHeightStyle.Trim.LastLineBottom

Чтобы узнать больше о контексте этого изменения, о том, как includeFontPadding работал в системе View, и об изменениях, внесенных в Compose и новые API LineHeightStyle, прочитайте запись блога Fixing Font Padding in Compose Text.

Вставить разрывы строк

LineBreak API определяет критерии, по которым текст разбивается на несколько строк. Вы можете указать нужный тип переноса строк в блоке TextStyle composable-функции Text. Существуют следующие типы переноса строк:

  • Simple – быстрый базовый перенос строк. Рекомендуется для полей ввода текста.
  • Heading – разрыв строки с менее строгими правилами. Рекомендуется для короткого текста, например заголовков.
  • Paragraph – более медленный, но качественный перенос строк для удобства чтения. Рекомендуется для больших объемов текста, например абзацев.

В следующем фрагменте кода используются оба свойства (Simple и Paragraph), чтобы задать перенос строк в длинном блоке текста:

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

Блок текста, в котором показана простая стратегия переноса строк, по сравнению с текстовым блоком со стратегией переноса, оптимизированной для абзацев. Блок текста с простой стратегией переноса строк имеет большую вариативность в длине строк.
Рисунок 1. Блок текста с простым переносом строк (вверху) и блок текста с переносом строк, оптимизированным для абзацев (внизу).

Обратите внимание, что в приведенном выше примере перенос строк Paragraph дает более визуально сбалансированный результат, чем перенос строк Simple.

Настроить разрывы строк

Вы также можете создать собственную конфигурацию LineBreak с помощью параметра Strategy. В качестве Strategy можно использовать:

  • Balanced – выравнивание длины строк текста, а также автоматический перенос слов, если он включен. Рекомендуется для небольших экранов, например часов, чтобы на них помещалось больше текста.
  • HighQuality – оптимизирует абзац для удобства чтения, в том числе с помощью переноса слов, если он включен. (Должно быть значением по умолчанию для всего, что не является Balanced или Simple.)
  • Simple – базовая быстрая стратегия. Если параметр включен, перенос выполняется только для слов, которые не помещаются на строке целиком. Это удобно при редактировании текста, чтобы не менять положение курсора во время ввода.

В следующем фрагменте кода показана разница между абзацем со стандартными настройками и абзацем, оптимизированным для небольших экранов с помощью стратегии переноса строк 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

Абзац со сбалансированной стратегией переноса строк и абзац, отформатированный без стратегии. Абзац со стратегией сбалансированного переноса строк имеет более согласованную длину строк, чем по умолчанию.
Рисунок 2. BalancedАбзац, отформатированный с использованием стратегии переноса строк (вверху), и абзац, отформатированный без использования стратегии переноса строк.

Особенности китайского, японского и корейского языков

Вы также можете настроить LineBreak с помощью API Strictness и WordBreak, которые были разработаны специально для китайского, японского и корейского языков. В языках, не относящихся к CJK, эффект от этих API может быть не всегда заметен. В целом правила переноса строк определяются на основе региональных настроек.

Strictness описывает строгость переноса строк со следующими свойствами:

  • Default – правила переноса по умолчанию для региональных настроек. Может соответствовать Normal или Strict.
  • Loose – наименее строгие правила. Подходит для коротких строк.
  • Normal – наиболее распространенные правила переноса строк.
  • Strict – самые строгие правила переноса строк.

WordBreak определяет, как должны вставляться разрывы строк внутри слов, и имеет следующие свойства:

  • Default – правила переноса по умолчанию для региональных настроек.
  • Phrase – перенос строк по фразам.

В следующем фрагменте кода для японского текста заданы строгий перенос строк (Strict) и перенос по словам (Phrase):

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

Японский текст со строгими настройками и настройками WordBreak по сравнению с текстом по умолчанию.
Рисунок 3. Текст, отформатированный с помощью настроек Strictness и WordBreak (вверху), и текст, отформатированный только с помощью настройки LineBreak.Heading (внизу).

Переносить слова по слогам

API Hyphens позволяет добавить в приложение поддержку переноса слов. Если эта функция включена, переносы добавляются между слогами в подходящих местах.

По умолчанию переносы отключены. Чтобы включить перенос слов, добавьте Hyphens.Auto в качестве параметра в блок 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

Абзац без переносов и абзац с переносами.
  Если включить перенос слов, то слово будет разделено дефисом и перенесено на две строки.
Рисунок 4. Абзац без переносов (сверху) и абзац с переносами (снизу).

Если перенос включен, он выполняется только при следующих условиях:

  • Слово не помещается в строке. Если вы используете стратегию переноса строк Simple, перенос слова происходит, только если строка короче одного слова.
  • На устройстве заданы подходящие региональные настройки, поскольку правильный перенос определяется с помощью словарей, имеющихся в системе.