← Назад к вопросам

В чем разница между px, dp и sp?

1.0 Junior🔥 161 комментариев
#Android компоненты#UI и вёрстка

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между px, dp и sp

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

px (Pixel)

px — это физический пиксель, абсолютная единица, привязанная к экрану. 1 px = 1 пиксель на экране.

Проблема:

  • На устройствах с разной плотностью пикселей (DPI/PPI) элементы выглядят по-разному
  • Экран с 150 DPI и 400 DPI с одинаковым px размером будут выглядеть очень по-разному
  • Невозможно создать адаптивный дизайн
// Плохо: не адаптивно
val view = TextView(this)
view.width = 200  // 200 пиксель - на разных устройствах разные размеры

Когда использовать px:

  • Почти никогда в реальных приложениях
  • Только для специальных случаев (draw операции, custom painting)
  • Для 1px бордюров (border в canvas)

dp (Density-Independent Pixel)

dp (или dip — Density Independent Pixel) — это логическая единица, которая масштабируется на основе плотности экрана.

Как это работает:

  • Система конвертирует dp в пиксели на основе DPI экрана
  • 1 dp = 1 пиксель на экране с плотностью 160 dpi (baseline)
1 dp = (screenDensity / 160) * 1 px

Примеры расчётов:

  • На экране 160 dpi: 1 dp = 1 px
  • На экране 320 dpi (2x плотность): 1 dp = 2 px
  • На экране 480 dpi (3x плотность): 1 dp = 3 px

Как получить density:

val density = context.resources.displayMetrics.density
val dpInPx = (16 * density).toInt()  // Конвертируем 16 dp в пиксели

Когда использовать dp:

  • Всегда для размеров элементов (width, height, padding, margin)
  • Для бордюров
  • Для расстояний между элементами
  • Для иконок
// Хорошо: адаптивно на всех устройствах
val button = Button(this)
button.width = 200.dp  // Специальный extension
button.height = 48.dp

// Или в XML
<Button
    android:layout_width="200dp"
    android:layout_height="48dp"
    android:padding="16dp"
    android:layout_margin="8dp" />

sp (Scale-independent Pixel)

sp (Scale-independent Pixel) — это то же самое, что dp, но ПЛЮС масштабируется на основе настроек размера шрифта пользователя.

Как это работает:

1 sp = (screenDensity / 160) * userFontScale

userFontScale по умолчанию = 1.0, но пользователь может изменить размер шрифта в настройках (Small, Normal, Large, Extra Large).

Пример:

  • Нормальный размер (100%): 1 sp = 1 dp
  • Большой размер (125%): 1 sp = 1.25 dp
  • Очень большой (200%): 1 sp = 2.0 dp

Когда использовать sp:

  • ВСЕГДА для размера текста (android:textSize)
  • Никогда для других размеров
// Хорошо: размер шрифта будет масштабироваться вместе с пользовательскими настройками
val textView = TextView(this)
textView.textSize = 16f  // По умолчанию в sp

// В XML
<TextView
    android:textSize="16sp"
    android:text="Hello World" />

Наглядное сравнение

ЕдиницаАдаптивнаяUser Font ScaleИспользуется дляПример
pxНетНетОчень редко (draw, border)1px line
dpДаНетРазмеры, отступы, иконкиButton width: 200dp
spДаДаРазмер текстаTextView textSize: 16sp

Практический пример

// ✅ Правильно
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">  // Отступ внутри
    
    <ImageView
        android:layout_width="48dp"      // Размер иконки
        android:layout_height="48dp"
        android:src="@drawable/ic_home" />
    
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"          // Размер шрифта
        android:layout_marginStart="8dp"  // Отступ элемента
        android:text="Home" />
</LinearLayout>

// ❌ Неправильно
<LinearLayout
    android:padding="16px">  // Не адаптивно
    
    <ImageView
        android:layout_width="48px"      // Очень неправильно для иконки
        android:layout_height="48px" />
    
    <TextView
        android:textSize="16dp" />        // Размер шрифта должен быть в sp
</LinearLayout>

Как конвертировать в коде

// Extension функции для удобства
val Int.dp: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()
val Int.sp: Float get() = this * Resources.getSystem().displayMetrics.scaledDensity

// Использование
val paddingInPx = 16.dp   // Конвертируем 16dp в пиксели
val textSize = 16.sp      // Конвертируем 16sp в пиксели

view.setPadding(16.dp, 16.dp, 16.dp, 16.dp)
textView.textSize = 16f   // по умолчанию в sp

Ключевое правило

Простое правило для запоминания:

  • dp = для всего визуального (размеры, отступы, иконки)
  • sp = только для текста
  • px = никогда не используй в приложениях

Это позволяет приложению автоматически масштабироваться на устройствах с разной плотностью пиксели и учитывает пожелания пользователя по размеру шрифта.