Android Screen Density & The 8dp Grid System
In modern Android application design, physical screen pixels (px) must never be hardcoded into XML layouts or Jetpack Compose Composables. Because physical pixel densities vary from 120 DPI up to 640+ DPI, a button sized at 100px would look huge on a low-end feature phone, yet render microscopically tiny and unclickable on a high-resolution flagship device.
The Golden Rule of the 8dp Grid
Why does Google Material Design mandate an 8dp baseline grid? Because 8 is cleanly divisible by all standard Android density scaling factors:
- ldpi (0.75x): 8dp × 0.75 = 6px (clean integer)
- mdpi (1.0x): 8dp × 1.0 = 8px (clean integer)
- hdpi (1.5x): 8dp × 1.5 = 12px (clean integer)
- xhdpi (2.0x): 8dp × 2.0 = 16px (clean integer)
- xxhdpi (3.0x): 8dp × 3.0 = 24px (clean integer)
- xxxhdpi (4.0x): 8dp × 4.0 = 32px (clean integer)
If a designer uses arbitrary odd values like 11dp or 13dp, scaling on an hdpi (1.5x) screen produces fractional pixels like 16.5px, forcing the Android graphics pipeline to anti-alias edges, producing blurry UI borders and jittery scrolling.
Jetpack Compose vs. Traditional View Pixel Conversion
Complete Android Density Qualifier Reference
| Qualifier | Density | Multiplier | 16dp in Pixels | Resource Directory |
|---|---|---|---|---|
ldpi | ~120 dpi | 0.75× | 12 px | res/drawable-ldpi/ |
mdpi (Baseline) | ~160 dpi | 1.0× | 16 px | res/drawable-mdpi/ |
hdpi | ~240 dpi | 1.5× | 24 px | res/drawable-hdpi/ |
xhdpi | ~320 dpi | 2.0× | 32 px | res/drawable-xhdpi/ |
xxhdpi (Most Devices) | ~480 dpi | 3.0× | 48 px | res/drawable-xxhdpi/ |
xxxhdpi (Flagships) | ~640 dpi | 4.0× | 64 px | res/drawable-xxxhdpi/ |
Frequently Asked Questions
android:viewportWidth="24" and android:width="24dp") to guarantee proper scaling across displays.