appdimens-dynamic

📚 Complete Guide: AppDimens Dynamic – All Calculations for Beginners

Quick Introduction

You write once and your code automatically adapts to any device. The library provides 12 different strategies, each with its own “growth formula”.


🎯 The 3 Core Pillars

1️⃣ SDP (Smallest Dimension Proportion) – The Smallest Side

Uses: SHORTEST side of the screen
Best for: Padding, spacing, general sizes

2️⃣ HDP (Height Dimension Proportion) – Height

Uses: Screen HEIGHT only
Best for: Component height, vertical lists

3️⃣ WDP (Width Dimension Proportion) – Width

Uses: Screen WIDTH only
Best for: Horizontal components

📊 The 12 Calculation Strategies

#1. SCALED (Default) ⭐

Reality check: In practice, Scaled is the strategy people use the most and it covers most everyday screens. Stick to plain sdp / hdp / wdp / ssp when you want simple proportional growth. Add a (aspect ratio), e.g. 16.sdpa or 16.sspa, when tall tablets or unusual aspect ratios need a smoother, refined adjustment — still Scaled, just with the extra flag.

Code:

// Compose
Modifier.padding(16.sdp)   // SDP
Modifier.height(100.hdp)   // HDP
Modifier.width(200.wdp)    // WDP
Text("Text", fontSize = 16.ssp)

// Views
DimenSdp.sdp(context, 16)

Formula (Simple):

Result = Value × (Screen_Size / 300)

What it means:

Example:

Phone 360 dp:   16 × (360/300) = 19.2 px
Tablet 480 dp:  16 × (480/300) = 25.6 px
Tablet 600 dp:  16 × (600/300) = 32 px
TV 1200 dp:     16 × (1200/300) = 64 px

When to use: ✅ Default layouts ✅ Spacing and padding ✅ General sizes ✅ Start here!


#2. AUTO (Automatic) ⭐⭐

Code:

Modifier.padding(16.asdp)
Modifier.height(100.ahdp)
Modifier.width(200.awdp)
Text("Text", fontSize = 16.assp)

Formula:

Up to 480 dp:
  Same as SCALED

Above 480 dp:
  Result = (480/300) × Value + 0.4 × ln(1 + (Size - 480) / 300)

What it means:

When to use: ✅ Phone + tablet with one token set ✅ When SCALED grows too much


#3. PERCENT

A) Screen share (space*) — the number is the %

Code:

Modifier.width(10.spaceW)   // 10% width
Modifier.height(20.spaceSw) // 20% smallest side

Formula:

Result = (Percentage / 100) × Screen_Size

What it means:

When to use: ✅ Grids, columns ✅ Exact percentages of width, height, or smallest width


B) Tokens like Scaled (psdp / phdp / pwdp / pssp) — percent strategy, same naming as sdp / hdp / wdp / ssp

Code:

import com.appdimens.dynamic.compose.percent.psdp
import com.appdimens.dynamic.compose.percent.phdp
import com.appdimens.dynamic.compose.percent.pwdp
import com.appdimens.dynamic.compose.percent.pssp

Modifier.padding(12.psdp)
Modifier.height(40.phdp)
Modifier.width(30.pwdp)
Text("Hi", fontSize = 14.pssp)
You want Typical extension Idea
SW-based (like sdp) 16.psdp Design token + percent strategy
Height axis 16.phdp Same pattern on height
Width axis 16.pwdp Same pattern on width
Text (like ssp) 16.pssp Sp on smallest-width axis, percent rules

Formula:

Without aspect ratio: same proportional idea as SCALED — roughly Value × (Axis / 300)
With `a`: percent strategy + aspect-ratio correction (library handles the curve)

What it means:

When to use: ✅ You want percent scaling rules but sdp-style names across the codebase
✅ Mixing with space* when some sizes are “% of axis” and others are tokens


#4. POWER (Sublinear Growth)

Formula:

Result = Value × (Size / 300)^0.75

What it means:

When to use: ✅ Icons ✅ Large displays (TVs, ultrawide)


#5. FLUID (Comfort Zone)

Formula:

≤320 dp → 0.8×  
≥768 dp → 1.2×  
Between → linear interpolation

What it means:

When to use: ✅ Typography on mobile ✅ Stable spacing


#6. DIAGONAL

Formula:

Diagonal = √(width² + height²)
Result = Value × (Diagonal / 611.63)

What it means:

When to use: ✅ Games ✅ Dashboards


#7. FILL (CSS “cover”)

Formula:

Result = Value × max(width_ratio, height_ratio)

What it means:

When to use: ✅ Backgrounds ✅ Hero sections


#8. FIT (CSS “contain”)

Formula:

Result = Value × min(width_ratio, height_ratio)

What it means:

When to use: ✅ Forms ✅ Reading layouts


#9. INTERPOLATED

Formula:

Result = Value + (Linear - Value) × 0.5

What it means:

When to use: ✅ Fine-tuning UI scaling


#10. LOGARITHMIC

Formula:

Result = Value × (1 + 0.4 × ln(Size / 300))

What it means:

When to use: ✅ One token for all devices


#11. PERIMETER

Formula:

Perimeter = width + height
Result = Value × (Perimeter / 833)

What it means:

When to use: ✅ Cards ✅ Thumbnails


#12. DENSITY (DPI-based)

Formula:

Result = Value × (DPI / 160)

What it means:

When to use: ✅ Legacy bitmap assets


🔧 Modifiers (Suffixes)

Suffix Meaning
(none) Default
a Aspect ratio adjustment
i Ignore split-screen
ia Both

🔄 Orientation Inverters

Inverter Behavior
Ph Height in portrait
Pw Width in portrait
Lw Width in landscape
Lh Height in landscape

📱 Quick Comparison

Need → Use

Default → SCALED  
Phone + Tablet → AUTO  
Exact % → PERCENT  
Slow growth → POWER  
Stable phone UI → FLUID  
Full screen → FILL  
No overflow → FIT  
Balanced → INTERPOLATED  
All devices → LOGARITHMIC  
Cards → PERIMETER  
Legacy → DENSITY

🚀 Practical Example

Card(
    modifier = Modifier
        .fillMaxWidth()
        .padding(
            horizontal = 16.sdp,
            vertical = 12.asdp
        )
) {
    Column(
        modifier = Modifier.padding(16.sdp)
    ) {
        Text(
            "My Card",
            fontSize = 24.ssp
        )

        Text(
            "Card description",
            fontSize = 16.ssp
        )

        Button(
            modifier = Modifier
                .height(48.sdp)
                .fillMaxWidth()
        ) {
            Text("Click", fontSize = 16.ssp)
        }
    }
}

💡 Final Tips

  1. Start with SCALED
  2. If it grows too much → use AUTO
  3. For universal tokens → use LOGARITHMIC
  4. For backgrounds → use FILL
  5. For reading → use FIT

🎓 Quick Recap

You only need 3 strategies to start:

  1. SCALED
  2. AUTO
  3. PERCENT

Modifiers:

Start simple and scale when needed. 🚀


📐 Resize — sizes that fit inside a box (not from screen formula alone)

Idea in plain words: Sometimes a number (font size, icon side, width) must be as large as possible but still fit inside the space the parent gives you — for example a long title in a card. Resize does not use the “screen ÷ 300” formula by itself; it tries several sizes (like steps on a ladder) until it finds the biggest one that still fits.

When to use: ✅ Headlines that must not overflow
✅ Icons or squares that should use “all the room” in a cell
✅ Anything where the parent size matters more than the global screen size

Rule: Call these functions only inside BoxWithConstraints { ... } — that block tells you how much width/height you really have.

Example — text that shrinks until it fits:

import androidx.compose.foundation.layout.BoxWithConstraints
import com.appdimens.dynamic.compose.resize.autoResizeTextSp

BoxWithConstraints(Modifier.fillMaxWidth()) {
    val fontSize = autoResizeTextSp(
        text = "Very long product name that might not fit",
        minSp = 12,
        maxSp = 28,
        stepSp = 1,
        maxLines = 2,
    )
    Text(
        text = "Very long product name that might not fit",
        fontSize = fontSize,
        maxLines = 2,
    )
}

What happens: The library tests 28 sp, 27 sp, 26 sp… down to 12 sp (or your stepSp) and picks the largest size where the text still fits in maxLines and the box.

Example — largest square that fits:

import com.appdimens.dynamic.compose.resize.autoResizeSquareSize

BoxWithConstraints(Modifier.fillMaxSize()) {
    val side = autoResizeSquareSize(min = 24, max = 120, step = 4)
    Box(Modifier.size(side)) { /* icon or avatar */ }
}

There are also helpers for width only, height only, and ranges based on % of the inner box — same idea: pick the biggest step that still fits.


📏 …Px extensions — when you need pixels, not Dp

Idea: 16.sdp gives a Dp for layouts. Sometimes you need a Float in px (Canvas, custom drawing, old interop).

Pattern: Add Px to the name.

val strokeWidthPx = 2f.sdpPx      // Float in px, SDP-based
val paddingPx = 16.hdpPx          // height axis, px

Same suffixes (a, i, ia, inverters) exist on many Px properties — check the API for your strategy.


🔤 sem / hem / wem — scalable Sp that ignores system font size

Problem: 16.ssp scales with the screen and usually follows the user’s font scale (Accessibility). Sometimes you want screen-based size but not to grow with “larger text” in settings.

Fix: “Fixed em” style extensions on the scaled strategy:

Extension Axis / meaning Use case
16.sem Smallest-width based Toolbar, fixed rhythm
16.hem Height-based Vertical emphasis
16.wem Width-based Horizontal emphasis
Text("Always same visual weight vs layout", fontSize = 14.sem)

You still get responsive sizing vs the device; you just don’t tie this particular text to system font scale the way ssp does.


🎛️ Facilitators — one value normally, another in special cases

Idea: Instead of if (orientation == …) everywhere, use one call that picks the right branch.

Family Example (SCALED) Plain English
Rotate 80.sdpRotate(50, Orientation.LANDSCAPE) “Usually 80 sdp; in landscape use 50 (scaled).”
Mode 30.sdpMode(200, UiModeType.TELEVISION) “Usually 30; on TV use 200 (scaled).”
Qualifier 60.sdpQualifier(120, DpQualifier.SMALL_WIDTH, 600) “If smallest width ≥ 600, use 120; else 60.”
Screen 70.sdpScreen(150, UiModeType.TELEVISION, DpQualifier.SMALL_WIDTH, 600) Combines mode + width threshold in one rule.

Many overloads accept Int, Dp, or “plain” variants — see the main README. Other strategies use the same names with their prefix (e.g. asdpRotate, pwsdpMode).

Plain with Dp / TextUnit (no extra scaling): When both the base and the alternate are already from the same strategy (e.g. 30.sdp and 20.sdp), use the overloads that take Dp or TextUnit as the alternate — only the branch (orientation, UI mode, qualifier, …) runs:

// Dp: both sides already scaled
val side = 30.sdp.sdpRotatePlain(20.sdp)

// Sp: both sides already scaled
Text("Hi", fontSize = 16.ssp.sspRotatePlain(12.ssp))

Nested facilitators: You can chain them; the effective order is how you nest the expression (evaluate outside → inside). For long chains, keep using Dp / TextUnit Plain alternates to avoid scaling the receiver or the alternate more than once.

Not the same as .screen: 100.scaledDp().screen(…).screen(…).sdp uses priorities inside DimenScaled — that order is not the same rule as “who is outside” in nested sdpRotatePlain / sdpModePlain calls. See COMPOSE-API-CONVENTIONS.md.


🧱 Builders — scaledDp() / scaledSp() (chain many rules)

Idea: Start from a number and chain options: aspect ratio, ignore multi-window, then several screen rules (TV, large sw, landscape…). At the end read .sdp, .hdp, .wdp or Sp.

val padding = 16.scaledDp()
    .aspectRatio(true)
    .ignoreMultiWindows(true)
    .screen(UiModeType.TELEVISION, 40)
    .screen(DpQualifier.SMALL_WIDTH, 600, 24)
    .sdp

Beginner tip: Use simple 16.sdp first; move to builders when one component needs many conditions.


📦 Physical units — real-world size (mm, cm, inch)

Idea: Say “10 mm on screen” instead of guessing dp. The library converts using the device’s density (so it’s only approximate physical size, like any Android dp).

Typical use: Rulers, print-like layouts, specs from design in mm or inch.

Easy Compose pattern: Use DimenPhysicalUnits.toMm / toCm / toInch with LocalResources — they return a Float in dp. Then use .dp:

import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.unit.dp
import com.appdimens.dynamic.compose.DimenPhysicalUnits

@Composable
fun RulerBar() {
    val resources = LocalResources.current
    val widthDp = DimenPhysicalUnits.toMm(10f, resources)   // 10 mm → dp
    val heightDp = DimenPhysicalUnits.toInch(0.25f, resources)
    Modifier
        .width(widthDp.dp)
        .height(heightDp.dp)
}

Inside the same @Composable, you can also use the shorthand 10f.mm, 2.5f.cm, 1f.inch if you import the extensions from DimenPhysicalUnits (see DOCUMENTATION/physical-units.md).

There are helpers in com.appdimens.dynamic.code.units for non-Compose code, plus radius from diameter, etc. Full table: DOCUMENTATION/physical-units.md.


✅ Checklist — “Did I miss something?”

Topic Remember
Resize Inside BoxWithConstraints; “largest size that still fits”
psdp / phdp / pwdp / pssp Percent strategy, same naming style as sdp / hdp / wdp / ssp (see #3 B)
…Px Float pixels for Canvas / custom drawing
sem / hem / wem Screen-scaled Sp without following system font scale like ssp
Rotate / Mode / Qualifier / Screen One-liner conditional sizing
scaledDp / scaledSp Chain many rules, then .sdp / .ssp
mm / cm / inch Real-world units → dp on screen

When in doubt, stay on SCALED (sdp / hdp / wdp) and add these tools only when a real layout problem appears.