Все статьи
23 сентября 2026 г.8 мин чтения

Лишние поля вокруг текста в Android: метрики шрифта и TextView

Лишние поля вокруг текста в Android: метрики шрифта и TextView

Если надпись в Android-кнопке выглядит утопленной, вокруг неё слишком много пустого места или нижние элементы букв обрезаются, причина может быть не в отступах макета, а в вертикальных метриках шрифта и правилах измерения текста. Разберём, как отличить эти случаи, проверить includeFontPadding в TextView, настроить строки в Compose и убедиться, что исправление не ломает кириллицу, масштабирование и другие языки.

Почему шрифт влияет на высоту текстового блока

Текст рисуется относительно базовой линии. Выше неё располагаются основные части букв и верхние выносные элементы, ниже — нижние выносные элементы. У шрифта есть вертикальные метрики, которые подсказывают системе, сколько места оставить над базовой линией, под ней и между строками. Это не то же самое, что видимая высота конкретного слова: слово «мама» может занимать меньше высоты, чем строка с «Й» или «у», но текстовый компонент измеряется по метрикам гарнитуры.

В Android Paint.FontMetrics различает ascent и descent — рекомендуемые расстояния для обычной строки — и более широкие границы top и bottom, которые учитывают самые высокие и низкие формы шрифта. Значения ascent и top обычно отрицательны, потому что направлены вверх от базовой линии; descent и bottom направлены вниз. Система использует их, чтобы размещать текст и не допускать столкновения соседних строк. Подробности есть в справке Android о FontMetrics.

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

Сначала определите, что именно выглядит неправильно

Не уменьшайте padding наугад. Сначала разделите четыре ситуации. Первая: вокруг одной короткой строки равномерно много пустоты — вероятны внутренние метрики шрифта или дополнительный запас компонента. Вторая: текст визуально смещён внутри кнопки — проверьте базовую линию, gravity и фактическую высоту. Третья: обрезаются акценты, верхушки или нижние выносные элементы — проверьте клиппинг, line height и метрики. Четвёртая: дефект возникает лишь у отдельных букв — сравните используемые шрифты и резервные подстановки.

Для диагностики временно задайте компоненту заметный фон, а строке — полупрозрачную подложку или рамку только в сборке для разработки. Снимите экран при одинаковых размерах текста с системным и пользовательским шрифтом. Затем сравните верхнюю и нижнюю границы контейнера с положением базовой линии и видимым контуром. Такой тест отделяет ошибку самого файла от настроек компонента: если системный шрифт центрируется, а пользовательский нет, макет, скорее всего, не единственный источник проблемы.

Проверьте не только условную строку «Текст», но и набор, который нагружает метрики: Йй Ёё, буквы с нижними выносными элементами, прописные, цифры и смешанный пример с названием бренда. Для многострочного текста добавьте абзац с несколькими строками. Контур знака может выходить за типичную высоту видимых строчных букв, а кириллические акценты и подстановки особенно легко пропустить при проверке одной короткой латинской подписи.

Что проверить в классическом TextView

У TextView есть параметр android:includeFontPadding. Документация Android описывает его как дополнительное место для восходящих и нисходящих элементов сверх строгих ascent и descent; обычно параметр включён. Поэтому на карточках с фиксированной высотой он иногда создаёт впечатление лишних полей. Это не универсальная ошибка: запас может быть нужен, чтобы некоторые акценты не обрезались. Описание параметра и методов доступно в API TextView.

Проверьте свой XML или тему оформления, а затем сравните один и тот же компонент с includeFontPadding="true" и false. Оставьте вариант, который верно показывает крайние знаки на поддерживаемых устройствах. Если вы отключаете дополнительный запас, перепроверьте надстрочные знаки, диакритику, текст на нескольких языках и нижние элементы букв. Значение false может убрать нежелательное пустое пространство, но также сокращает область, выделяемую тексту.

Для короткой кнопки отдельная проблема — привязка к центру контейнера вместо базовой линии. Сверьте gravity, верхние и нижние padding, а также minHeight и фиксированную height. Не компенсируйте высокие метрики отрицательным отступом: знак может нормально выглядеть в одном состоянии и обрезаться в другом. Если дизайн задаёт расстояние от контейнера до строки, пользуйтесь функциями первой базовой линии на поддерживаемых версиях Android, а не подбирайте магическое число по скриншоту.

Для текста в несколько строк проверьте lineSpacingExtra, множитель межстрочного интервала и явный lineHeight. Когда line height меньше нужных метрик, контуры строк могут сближаться или обрезаться. Особенно важно повторить тест со знаком, который использует fallback-шрифт: начиная с Android 9 (API 28) TextView предоставляет настройку, позволяющую учитывать ascent и descent резервных шрифтов при вычислении строк. Не отключайте это поведение просто ради более компактной верстки, если в приложении есть другие письменности.

Пример диагностической проверки в XML может выглядеть так: <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:includeFontPadding="false" android:text="Йй Ёё" />. Используйте такой вариант как тест, а не как готовое глобальное правило. Сравните его с исходным стилем, просмотрите границы элемента в инспекторе макета и проверьте, что итоговый размер не зависит от того, поместилось слово в одну строку или перенеслось.

Если экран сделан на Jetpack Compose

В Compose настройка дополнительных полей тоже называется includeFontPadding, но её значение зависит от версии стека. Официальное руководство сообщает, что начиная с Compose BOM 2024.01.01 параметр по умолчанию отключён. Если проект давно обновлялся или задаёт собственный PlatformTextStyle, не предполагайте, что все версии ведут себя одинаково: проверьте версию BOM и явные значения в коде. Подробнее — в руководстве Android по стилю абзаца в Compose.

У Text можно настроить lineHeight, а LineHeightStyle управляет выравниванием текста в этой области и сохранением свободного места сверху первой и снизу последней строки. Меняйте эти параметры по одному: сначала добейтесь корректной высоты, затем настройте расположение строки внутри неё. Слишком маленький lineHeight способен скрыть крайние элементы; чрезмерно большой делает подписи рыхлыми. Пример в документации полезен как способ управления пробелом, но значение для своего приложения нужно выбирать по живым текстовым сценариям.

Не пытайтесь сделать визуально одинаковую высоту кнопок просто через одинаковое число sp или одинаковое значение line height. У разных гарнитур различаются пропорции, а резервный шрифт может быть выше основного. Для компонента важнее предсказуемые края, базовая линия и пространство на перенос. Сохраняйте функциональную область нажатия независимо от того, насколько компактно выглядит рисунок букв.

Порядок проверки перед выпуском

  1. Зафиксируйте исходное состояние: устройство или эмулятор, плотность экрана, версия Android, размер системного текста, локаль, семейство и начертание шрифта.
  2. Найдите точный компонент и проверьте ограничения родителя: заданную высоту, клиппинг, отступы, выравнивание и число строк.
  3. Сравните системный шрифт и пользовательскую гарнитуру на одной и той же кириллической тестовой строке.
  4. Меняйте по одному параметру: сначала includeFontPadding, затем высоту строки или привязку к базовой линии. Записывайте, что именно изменилось.
  5. Повторите тест в одно- и многострочном виде, с акцентами, цифрами и символами, которые могут перейти в другой шрифт.
  6. Увеличьте системный размер текста и проверьте, что надпись не обрезается и важное действие не теряется за фиксированной высотой.
  7. Просмотрите релизную сборку на минимальной и актуальной версии Android, которую поддерживает продукт.

Для снимков сравнивайте одинаковый масштаб, размер шрифта и состояние устройства. Скриншот без рамок не показывает, где заканчивается область TextView, поэтому для первого этапа диагностики границы элемента важнее эстетики снимка. После того как причина найдена, удалите отладочные подложки, но сохраните тестовый текст и сценарий в регрессионной проверке интерфейса.

Частые ошибки

  • Уменьшать padding, когда проблема вызвана шириной метрик или заданной высотой элемента.
  • Отключать includeFontPadding сразу у всех подписей: разные гарнитуры и письменности требуют разных проверок.
  • Задавать маленький фиксированный lineHeight, чтобы приблизить строки, не проверяя диакритические знаки и fallback.
  • Выравнивать подпись визуально отрицательным отступом, а затем забывать проверить перенос текста.
  • Считать, что одно и то же значение Compose и классического TextView ведёт себя одинаково во всех версиях библиотек.
  • Проверять только английский набор и пропускать кириллицу, дополнительные языки и динамическое увеличение текста.

Чек-лист для компонента с пользовательским шрифтом

  • Уточните, используется ли TextView, Compose Text или компонент поверх них.
  • Проверьте высоту родителя, внутренние поля, line height, baseline и клиппинг.
  • Сравните системную и пользовательскую гарнитуры при одинаковых условиях.
  • Прогоните строку с русскими буквами, акцентами, цифрами и несколькими строками.
  • Проверьте поведение при увеличенном размере текста и при переносе.
  • Оставьте настройку includeFontPadding только после проверки крайних контуров и локалей.
  • Сохраните скриншот и параметры устройства, чтобы повторить тест после обновления шрифта или Android.

Частые вопросы

Можно ли всегда задавать includeFontPadding="false"?

Нет. В TextView этот параметр регулирует запас для восходящих и нисходящих элементов. Отключение бывает полезно, когда запас мешает выровнять короткую подпись, но после изменения нужно проверить акценты, нижние элементы букв, многострочный набор и fallback-шрифты.

Почему проблема проявляется только на русском тексте?

Кириллические буквы, акценты и символы из других алфавитов могут использовать контуры с другой высотой или резервную гарнитуру. Проверьте русскую строку с Й, Ё и нижними выносными элементами, а также смешанный текст. Латинский пример не всегда выявляет разницу.

Что выбрать: wrap_content или фиксированную высоту?

Для обычной подписи wrap_content снижает риск обрезки при изменении текста, но сам по себе не гарантирует хорошего выравнивания. Фиксированная высота уместна, если она рассчитана на реальный диапазон текстовых размеров и многострочность. Не закрывайте переполнение без проверки увеличенного системного текста.

Почему после обновления Compose строки стали выглядеть иначе?

В документации Android указано, что Compose BOM версии 2024.01.01 отключает includeFontPadding по умолчанию. Изменение может повлиять на вертикальное размещение текста и работу LineHeightStyle. Сверьте версию BOM, PlatformTextStyle и явно заданный lineHeight в стилях приложения.

Как проверить шрифт без специального прибора?

Используйте рамку компонента в режиме отладки, несколько тестовых строк и снимки экрана с зафиксированными параметрами. Сравните системную и пользовательскую гарнитуры при одном кегле, потом меняйте один параметр за раз. Для типографической проверки собственного алфавита можно собрать набор в Fontgenerator и повторить те же строки в тестовом экране.

Итог

Лишнее пространство и обрезанные знаки могут возникать из-за вертикальных метрик шрифта, внутренних правил компонента или ограничений макета. Сравните includeFontPadding, базовую линию и lineHeight на тестовых кириллических и многострочных примерах, затем проверьте увеличение текста и резервные шрифты. Так вы исправите конкретную причину, не потеряв запас, нужный другим символам и пользователям.