sp: что это, масштабируемые пиксели для текста в Android

Автор: IT Sectr Опубликовано: 2026-02-25 Время чтения: 9 мин

sp — Scale-independent Pixels, единица измерения текста в Android, учитывающая настройки размера шрифта на устройстве. В отличие от dp, sp масштабируется вместе с системным кеглем, обеспечивая доступность интерфейсов. Статья объясняет разницу между sp и dp, показывает настройку textSize в XML и Kotlin, а также раскрывает лучшие практики работы с типографикой в Android.

Главное

  • sp — единица для текста, масштабируемая под системные настройки шрифта пользователя
  • dp — единица для размеров элементов, не реагирует на изменение кегля
  • Разница sp и dp: sp = dp × scaleFactor, где scaleFactor зависит от настроек шрифта
  • textSize в XML задаётся через sp: android:textSize="16sp"
  • Material Design рекомендует шаг типографики от 12sp до 34sp для заголовков

Что такое sp в Android?

sp (scale-independent pixel) — единица измерения размера шрифта в Android, которая автоматически масштабируется в соответствии с системными настройками пользователя. Когда владелец устройства увеличивает размер шрифта в настройках, все элементы со значениями в sp пропорционально растут. Это обеспечивает доступность интерфейса для людей с ослабленным зрением.

Базовое соотношение: 1 sp = 1 dp при стандартном масштабе шрифта 1.0 (normal). Если пользователь устанавливает шрифт Large (1.15×), 16 sp превращается в 18.4 физических пикселя. При размере шрифта Small (0.85×) те же 16 sp станут 13.6 px. Механизм масштабирования управляется через Settings.System.FONT_SCALE на уровне Android Framework.

По данным Google Material Design Guidelines, текст должен задаваться исключительно в sp. Исключение — фиксированные подписи в компонентах, где размер критичен для компоновки (например, текст внутри кнопок фиксированной высоты). В таких случаях рекомендуется использовать dp с ручным контролем доступности.

sp vs dp: ключевые отличия

Разница между sp и dp — одна из самых частых тем вопросов на собеседованиях Android-разработчиков и в реальных code review. Обе единицы привязаны к density-independent pixel (160 dpi = 1 dp = 1 px на экране mdpi), но ведут себя по-разному при изменении системного кегля.

Характеристикаspdp
НазначениеРазмер текстаРазмеры элементов, отступы, ширина, высота
Масштабирование под шрифтДа (scale factor)Нет
Масштабирование под плотностьДаДа
API для установкиandroid:textSizeandroid:layout_width, layout_height, padding, margin
Material Design Tokentypescalespacing, sizing

На практике ошибка — использовать dp для текста. Если текст задан в dp, он не масштабируется при увеличении шрифта, что делает интерфейс недоступным для пользователей с плохим зрением. Обратная ошибка — использовать sp для высоты кнопки или отступов: при увеличении шрифта кнопка может «раздуться», сломав компоновку.

Как работает масштабирование sp

Масштабирование sp реализовано на уровне Android Framework в классе TypedValue. Формула пересчёта: sp = dp × scaledDensityD, где scaledDensityD — масштабный коэффициент, учитывающий как плотность экрана, так и настройку шрифта пользователя.

kotlin
// Программное получение scaledDensity в Kotlin
val scaledDensity = with(context.resources) {
    displayMetrics.scaledDensity
}

// Перевод sp в px
fun spToPx(sp: Float, context: Context): Float {
    return TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_SP,
        sp,
        context.resources.displayMetrics
    )
}

// Перевод px в sp
fun pxToSp(px: Float, context: Context): Float {
    return px / context.resources.displayMetrics.scaledDensity
}

Метод TypedValue.applyDimension — единственный правильный способ конвертации sp в пиксели в runtime. Прямое умножение на scaledDensity менее надёжно, так как не обрабатывает edge-кейсы (нулевые значения, переполнение). scaledDensity меняется при изменении настроек шрифта через Settings > Display > Font size.

Коэффициенты масштабирования

Android предоставляет пять предустановленных уровней масштаба шрифта: Small (0.85×), Default (1.0×), Large (1.15×), Largest (1.3×) и дополнительный уровень для Very Large (>1.3×) в Android 14+. Производители устройств (Samsung, Xiaomi) добавляют собственные уровни — вплоть до 2.0×. Минимальный размер текста в sp никогда не гарантирует фиксированное количество пикселей.

Использование sp в XML-разметке

В XML-разметке sp применяется исключительно в атрибуте android:textSize. Все остальные размеры — width, height, padding, margin, elevation — задаются в dp. Правило простое: если элемент отображает текст — его размер в sp, если элемент определяет геометрию — размер в dp.

Базовый пример textSize в XML

xml
<!-- Разметка TextView с textSize в sp -->
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:textSize="16sp"
    android:padding="12dp"
    android:lineSpacingExtra="4dp" />

<!-- Использование dimens-ресурсов -->
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/text_body_large" />

Рекомендуется выносить размеры текста в файл dimens.xml. Это упрощает поддержку типографики, позволяет переопределять размеры для разных конфигураций экрана и обеспечивает единообразие во всём приложении.

dimens.xml с типографическими токенами

xml
<!-- res/values/dimens.xml -->
<resources>
    <!-- Material Design Type Scale -->
    <dimen name="text_display_large">34sp</dimen>
    <dimen name="text_display_medium">28sp</dimen>
    <dimen name="text_headline_large">24sp</dimen>
    <dimen name="text_headline_medium">20sp</dimen>
    <dimen name="text_title_large">18sp</dimen>
    <dimen name="text_body_large">16sp</dimen>
    <dimen name="text_body_medium">14sp</dimen>
    <dimen name="text_label_large">14sp</dimen>
    <dimen name="text_label_small">11sp</dimen>
</resources>

Material Design Type Scale включает 13 уровней размеров — от 11sp для мелких подписей до 57sp для крупных дисплейных заголовков. Android-проекты обычно используют 8–10 уровней. Все значения должны быть кратны 1sp — дробные значения (15.5sp) ухудшают рендеринг из-за субпиксельного позиционирования.

Настройка типографики через Kotlin

В современной Android-разработке текст редко задаётся напрямую через textSize в sp. Вместо этого используется система MaterialTheme.typography, где каждый стиль предопределён и включает размер, вес, межстрочный интервал и letter-spacing.

kotlin
// Кастомная типографика через Typography API
val AppTypography = Typography(
    displayLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 34.sp,
        lineHeight = 40.sp,
        letterSpacing = 0.sp
    ),
    headlineLarge = TextStyle(
        fontWeight = FontWeight.SemiBold,
        fontSize = 24.sp,
        lineHeight = 32.sp
    ),
    titleLarge = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 18.sp,
        lineHeight = 24.sp
    ),
    bodyLarge = TextStyle(
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        lineHeight = 24.sp,
        letterSpacing = 0.5.sp
    ),
    labelSmall = TextStyle(
        fontWeight = FontWeight.Medium,
        fontSize = 11.sp,
        lineHeight = 16.sp,
        letterSpacing = 0.5.sp
    )
)

Функция-расширение .sp в Jetpack Compose автоматически транслируется в scale-independent pixels. При изменении системного кегля Compose пересчитывает fontSize, lineHeight и spacing в соответствии с новым scaledDensity. TextUnit (класс, представляющий sp) гарантирует, что текст масштабируется, а отступы — нет.

sp в Jetpack Compose

В Jetpack Compose sp представлен типом TextUnit, который не может быть случайно использован для размеров элементов. Компилятор Kotlin выдаёт ошибку, если передать TextUnit туда, где ожидается Dp. Это устраняет целый класс багов, связанных с неправильным масштабированием.

kotlin
// TextUnit в Compose — безопасная работа со sp
@Composable
fun ArticleCard(title: String, description: String) {
    Card(modifier = Modifier
        .fillMaxWidth()
        .padding(16.dp)
    ) {
        Text(
            text = title,
            style = MaterialTheme.typography.titleLarge
        )
        Spacer(modifier = Modifier.height(8.dp))
        Text(
            text = description,
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

// Явное задание fontSize в sp
Text(
    text = "Кастомный размер",
    fontSize = 20.sp,
    fontWeight = FontWeight.Bold,
    color = MaterialTheme.colorScheme.primary
)

В Compose нет прямого эквивалента XML-атрибута android:textSize — размер текста задаётся через TextStyle.fontSize. Система MaterialTheme.typography предоставляет предопределённые стили, которые соответствуют Material Design Type Scale. Если нужен кастомный размер, используется литерал 20.sp — язык гарантирует, что это TextUnit, а не Dp.

Лучшие практики работы со sp

Правильное использование sp — основа доступного Android-приложения. Ниже собраны правила, основанные на рекомендациях Google Material Design и Android Developers Guide.

  • Всегда используйте sp для текста — никогда не задавайте textSize в dp или px, иначе пользователи с увеличенным шрифтом не смогут читать интерфейс
  • Используйте dp для контейнеров — высота кнопок, отступы и ширина карточек должны быть в dp, иначе при большом шрифте элементы могут перекрываться
  • Выносите размеры в dimens.xml — централизованное хранение типографических токенов упрощает рефакторинг и поддержку тёмной темы
  • Не используйте sp меньше 12sp — текст меньшего размера становится нечитаемым на устройствах с высоким PPI и при стандартном кегле
  • Тестируйте при максимальном масштабе шрифта — включите в настройках устройства самый крупный шрифт и проверьте, что интерфейс не ломается

Главное правило доступности: пользователь должен иметь возможность увеличить шрифт без потери функциональности. Если приложение корректно работает при масштабе шрифта 1.3×, оно пройдёт базовые тесты accessibility. Google Play может отклонить приложение, если textSize задан в dp и интерфейс не масштабируется.

Часто задаваемые вопросы

Чем sp отличается от dp?

sp (scale-independent pixel) масштабируется при изменении системного размера шрифта, а dp — нет. sp используется только для текста, dp — для всех остальных размеров элементов. Коэффициент пересчёта: sp = dp × FONT_SCALE.

Можно ли использовать sp для отступов?

Нет. Отступы, высота кнопок, ширина карточек должны задаваться в dp. Использование sp для отступов приводит к тому, что при увеличении шрифта элементы растут неестественно и могут выходить за границы экрана.

Как проверить, что приложение корректно работает с sp?

Откройте Settings > Display > Font size и установите максимальное значение (Largest). Запустите приложение и проверьте, что весь текст читается, элементы не накладываются друг на друга, а кнопки не выходят за границы экрана. Для автоматизации используйте Espresso с UiAutomator.

Какой минимальный размер текста в sp допустим?

Material Design рекомендует минимальный размер 11sp для labelSmall. Для основного текста — от 14sp (bodyMedium) до 16sp (bodyLarge). Размеры меньше 11sp не рекомендуются, так как становятся нечитаемыми на устройствах с высокой плотностью пикселей.

Что произойдёт, если задать textSize в dp?

Текст будет отображаться в фиксированном размере независимо от системных настроек шрифта. Пользователи с увеличенным шрифтом не смогут комфортно читать такой текст. Это нарушает требования доступности WCAG и может стать причиной отклонения приложения в Google Play.

Итоги

  • sp — единица измерения шрифта в Android, масштабируемая под настройки пользователя через FONT_SCALE
  • dp — единица для размеров элементов, не реагирующая на изменение кегля
  • textSize в XML задаётся через android:textSize="16sp", все остальные размеры — в dp
  • MaterialTheme.typography в Jetpack Compose использует TextUnit (.sp) для безопасности типов
  • dimens.xml — централизованное хранение типографических токенов для единообразия
  • Минимальный размер текста — 11sp, рекомендуемый для body — 14–16sp
  • Тестирование при максимальном масштабе шрифта — обязательный этап проверки доступности

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также