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 × scaledDensity, де scaledDensity — масштабний коефіцієнт, що враховує як щільність екрану, так і налаштування шрифту користувача.

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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

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