One dependency: you write values like 16.sdp and the library scales them from the current screen Configuration (size, density, optional flags).
New here? Use Quick start below, then GUIDE-FOR-BEGINNERS for every strategy in plain language.
All 14 modes (scaled, percent, power, fluid, …): DOCUMENTATION/README.md · KDoc (hosted)
dependencies {
implementation("io.github.bodenberg:appdimens-dynamic:3.1.0")
}Requirements: Min SDK 24 · Compile SDK 36 · Kotlin & Java 17 · Jetpack Compose (BOM aligned with this library)
Scaled uses 300 dp as the design reference. It is the most widely used strategy in real apps and the recommended default: use plain sdp / hdp / wdp / ssp when a single curve is enough, and the a suffix (aspect ratio–aware), e.g. 16.sdpa, when you want scaling tuned to screen shape. After Scaled, the next strategies teams typically adopt are percent (sizes as a fraction of an axis) and auto (breakpoint-style steps); the other modes are for specialized layouts — see DOCUMENTATION/README.md.
| Extension | Based on | Typical use |
|---|---|---|
sdp |
Smallest window width | Padding, margins |
hdp |
Screen height | Row height |
wdp |
Screen width | Column width |
ssp |
Same idea as sdp, for text |
fontSize |
import com.appdimens.dynamic.compose.*
Box(
Modifier
.padding(16.sdp)
.width(100.wdp)
.height(48.hdp)
) {
Text("Hello", fontSize = 16.ssp)
}If you only use sdp / hdp / wdp / ssp (and variants like sdpa), you can skip this block.
Use it when you call .sdpMode, .sdpScreen, .sspMode, .sspScreen, or similar facilitators that depend on UI mode / fold state. It sets LocalUiModeType once for the tree instead of resolving mode on every call.
import com.appdimens.dynamic.core.AppDimensProvider
setContent {
AppDimensProvider {
MyApp()
}
}Call this when the same Activity stays alive across rotation, split-screen, or density/font changes and sizes look stale. If the Activity is recreated on config change (default), you often don’t need it. Details: library/PERFORMANCE.md.
import android.content.res.Configuration
import com.appdimens.dynamic.core.DimenCache
private var lastConfiguration: Configuration? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lastConfiguration = Configuration(resources.configuration)
}
override fun onConfigurationChanged(newConfig: Configuration) {
DimenCache.invalidateOnConfigChange(lastConfiguration, newConfig)
lastConfiguration = Configuration(newConfig)
super.onConfigurationChanged(newConfig)
}You only get onConfigurationChanged if the Activity lists android:configChanges for those changes in the manifest; otherwise the process usually recreates the Activity and config is fresh automatically.
| Suffix | Meaning |
|---|---|
| (none) | Default |
a |
Aspect ratio–aware curve |
i |
Ignore multi-window heuristic (may return unscaled base when it triggers) |
ia |
Both |
16.sdpa // + aspect ratio
32.hdpi // height axis + ignore multi-window
16.sspa // scalable sp + aspect ratioText("Scaled (sw)", fontSize = 16.ssp)
Text("Scaled (height)", fontSize = 20.hsp)
Text("Scaled (width)", fontSize = 18.wsp)
Text("No system font scale (sw)", fontSize = 16.nem) // nem / hem / wem32.sdpPh // SW-based; in portrait uses height
32.sdpLw // SW-based; in landscape uses width
50.hdpLw // Height-based; in landscape uses width
50.wdpLh // Width-based; in landscape uses heightimport com.appdimens.dynamic.compose.*
import com.appdimens.dynamic.common.DpQualifier
import com.appdimens.dynamic.common.Orientation
import com.appdimens.dynamic.common.UiModeType
80.sdpRotate(50, orientation = Orientation.LANDSCAPE)
30.sdpMode(200, UiModeType.TELEVISION)
60.sdpQualifier(120, DpQualifier.SMALL_WIDTH, 600)
16.sspRotate(24, orientation = Orientation.LANDSCAPE)Full catalog: DOCUMENTATION/COMPOSE-API-CONVENTIONS.md.
val pad = 16.scaledDp()
.aspectRatio(true)
.screen(UiModeType.TELEVISION, 40)
.screen(DpQualifier.SMALL_WIDTH, 600, 24)
.sdpPicks the largest font or size in a min…max range that still fits the space. Use for titles, squares, etc.
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.ui.Modifier
import com.appdimens.dynamic.compose.resize.autoResizeTextSp
BoxWithConstraints(Modifier.fillMaxWidth()) {
val fontSize = autoResizeTextSp(
text = "Headline that must fit",
minSp = 12,
maxSp = 28,
stepSp = 1,
maxLines = 2,
)
Text("Headline that must fit", fontSize = fontSize, maxLines = 2)
}More APIs (autoResizeSquareSize, ResizeBound, …): DOCUMENTATION/resize.md.
import com.appdimens.dynamic.code.DimenSdp
import com.appdimens.dynamic.code.DimenSsp
val paddingPx = DimenSdp.sdp(context, 16)
val heightPx = DimenSdp.hdp(context, 32)
val widthPx = DimenSdp.wdp(context, 100)
val fontPx = DimenSsp.ssp(context, 16)
// Extensions (see code package)
// 16.ssp(context), DimenSdp.scaled(16).screen(...).sdp(context), sdpRotate, …import com.appdimens.dynamic.code.DimenSdp;
import com.appdimens.dynamic.code.DimenScaled;
import com.appdimens.dynamic.code.DimenSsp;
import com.appdimens.dynamic.common.UiModeType;
float paddingPx = DimenSdp.sdp(context, 16);
float heightPx = DimenSdp.hdp(context, 32);
float fontPx = DimenSsp.ssp(context, 16);
DimenScaled scaled = DimenSdp.scaled(16)
.applyAspectRatio(true)
.screen(UiModeType.TELEVISION, 32);
float result = scaled.sdp(context);Approximate real-world size on screen (density-based). Compose: use helpers from the library and .dp on the result where needed — see DOCUMENTATION/physical-units.md. Code module: com.appdimens.dynamic.code.units.DimenPhysicalUnits (toDpFromMm, …).
Recommendation order for most apps: Scaled (with or without a) → then percent → then auto; explore the rest when you have a clear need (fluid, fit, diagonal, etc.).
Other strategies (percent, power, fluid, auto, diagonal, fill, fit, interpolated, logarithmic, perimeter, density) use the same suffix patterns as Scaled with a different import prefix — see DOCUMENTATION/README.md and GUIDE-FOR-BEGINNERS.
| Resource | Use for |
|---|---|
| DOCUMENTATION/README.md | Per-strategy explanations |
| COMPOSE-API-CONVENTIONS.md | Every Compose property & facilitator (scaled catalog + prefix map) |
| DOCUMENTATION/index.md | Markdown API index (KDoc export) |
| appdimens3.web.app | Searchable KDoc |
Example app: app/.../compose/ExampleActivity.kt (includes auto-resize demos).
- Results are cached in
DimenCache(lock-free, optional persistence). - Some paths skip storing in the shard table when a cheap multiply is enough — see library/PERFORMANCE.md.
- Batch / low-level keys: not needed for normal app code; library extensions already use the cache.
- Code-only scaling (no XML dimen grids) · SDP / HDP / WDP + 14 scaling modes
- Aspect ratio & multi-window flags · Inverters & facilitators · Foldable awareness via WindowManager
- Physical units · Resize helpers · DimenScaled chains
Apache License 2.0 — responsive layout utilities for Android.


