Dimensions & Density (Java)
Every layout needs consistent spacing and sizing, and Android gives you two tools for that: dimens.xml for defining reusable values once, and the dp unit for making sure those values look the same physical size on every device. This lesson covers both, plus how density buckets decide which image file a device actually loads.
1. dimens.xml — Centralizing Sizes
Just like colors and strings get their own resource files, sizes belong in res/values/dimens.xml. Instead of typing 16dp as a magic number in a dozen layouts, you define it once and reference it everywhere — so changing the app's spacing later means editing one line, not hunting through every XML file.
<!-- res/values/dimens.xml -->
<resources>
<dimen name="card_padding">16dp</dimen>
<dimen name="card_margin">8dp</dimen>
<dimen name="card_corner_radius">12dp</dimen>
<dimen name="title_text_size">18sp</dimen>
</resources>
<!-- Every RecipeBox recipe card references the same values -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/card_margin"
app:cardCornerRadius="@dimen/card_corner_radius">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="@dimen/card_padding">
<TextView
android:id="@+id/tvRecipeTitle"
android:textSize="@dimen/title_text_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</androidx.cardview.widget.CardView>
- Every RecipeBox card — in the recipe list, the detail screen, even a "similar recipes" strip — pulls @dimen/card_padding and @dimen/card_margin from the same source.
- Want tighter spacing across the whole app? Change two lines in dimens.xml instead of editing every layout file.
2. Why dp Exists
Two phones can have the exact same physical screen size — say, 6 inches diagonally — yet pack wildly different numbers of physical pixels into that space. One might have 1080 pixels across; another, 1440. If you sized a button as "200 pixels wide" on both, it would look almost twice as wide, physically, on the lower-resolution screen. A raw pixel value simply doesn't describe a consistent physical size across devices.
dp (density-independent pixel) solves this. Android defines dp relative to a baseline density (160 dpi, called mdpi) and automatically scales it up or down based on the actual device's density. The result: 1dp always renders as roughly the same physical size, whether the screen crams in 160 pixels per inch or 480. You describe layout sizes in dp, and Android handles the pixel math per device.
3. Density Buckets
Android groups the enormous range of real device densities into a handful of standard buckets. Each bucket has an approximate scale factor relative to the mdpi baseline:
| Bucket | Approx. density (dpi) | Scale factor | Example devices |
|---|---|---|---|
| ldpi | ~120 | 0.75x | Very old, low-end phones |
| mdpi | ~160 | 1x (baseline) | Older baseline phones |
| hdpi | ~240 | 1.5x | Older mid-range phones |
| xhdpi | ~320 | 2x | Common mid-range phones |
| xxhdpi | ~480 | 3x | Many modern flagship phones |
| xxxhdpi | ~640 | 4x | High-end phones, large tablets |
4. Density-Specific Drawable Folders
The previous lesson, Drawables & Vector, introduced vector drawables as a way to ship exactly one icon file for every density. Bitmap images (PNG/JPG photos, or icons that genuinely can't be vectors) don't get that luxury — a raster image has a fixed pixel grid, so a single PNG that looks sharp on mdpi will look soft and blurry when stretched for xxhdpi.
The traditional fix is to export the same image at multiple resolutions and place each version in its matching density folder. Android automatically picks the right file for the running device:
res/
├─ drawable-mdpi/recipe_placeholder.png // 1x — smallest
├─ drawable-hdpi/recipe_placeholder.png // 1.5x
├─ drawable-xhdpi/recipe_placeholder.png // 2x
├─ drawable-xxhdpi/recipe_placeholder.png // 3x
└─ drawable-xxxhdpi/recipe_placeholder.png // 4x — largest, sharpest
5. sp for Text Size — A Quick Recap
sp (scale-independent pixel) behaves like dp for text: it scales consistently with screen density, but it additionally respects the user's own font-size preference set in system accessibility settings. This was covered in Colors & Typography — the short version is: always use sp for android:textSize, and reserve dp for everything else (widths, heights, margins, padding, icon sizes). Mixing them up is a common source of text that ignores a user's accessibility settings.
6. Choosing Dimension Values in Practice
A practical rule of thumb that reads comfortably across common phone and tablet sizes:
- Tight spacing (between related elements, like an icon and its label): 4dp–8dp.
- Standard spacing (card padding, margins between sections): 16dp is the most common default across Android apps.
- Generous spacing (separating unrelated sections, screen edges on tablets): 24dp–32dp.
- Touch targets (buttons, icons meant to be tapped): at least 48dp — this is an accessibility minimum covered in more depth in the upcoming Accessibility lesson.