AppDimens
May 13, 2026 · View on GitHub
AppDimens — Smart Responsive Dimensions for Any Screen
A family of responsive sizing libraries that replaces fragile dp / sp / pt / px with explicit, perceptual scaling kernels — same vocabulary, same math, across Android, Apple, KMP, Flutter, React Native and the Web.
Platform repositories (quick reference)
Each implementation lives in its own GitHub repository (not only the submodules in this hub). Status reflects the current product line described in that repo’s README.
| Repository | Platform | Status |
|---|---|---|
| appdimens-dynamic | Android — Jetpack Compose, Kotlin Views, Java Views | Production |
| appdimens-sdps | Android — XML @dimen SDP-style resources (+ Compose tokens) | Production |
| appdimens-ssps | Android — XML SSP-style text resources (+ Compose tokens) | Production |
| appdimens-games | Android — game / NDK sizing helpers | Work in progress |
| appdimens-ios | Apple — iOS / iPadOS / macOS (UIKit, SwiftUI, Metal) | Work in progress |
| appdimens-dynamic-kmp | Kotlin Multiplatform | Work in progress |
| appdimens-flutter | Flutter — Android, iOS, Web, desktop | Work in progress |
| appdimens-react-native | React Native — iOS & Android | Work in progress |
| appdimens-web | Web — vanilla JS, React, Vue, Svelte, Angular | Work in progress |
Details, coordinates, and semver: see Platform matrix below.
Tip
TL;DR — Plain dp / sp / pt / px factor out density but not canvas extent or aspect ratio. AppDimens models token sizing as a family of one-dimensional maps with explicit kernels (linear, hybrid linear–logarithmic, Weber–Fechner, Stevens, fluid clamp, geometric, letterbox/fill, density buckets, constraint-based resize) and gives you the same vocabulary on every platform so a 16.sdp on Android Compose, a balanced(16) on iOS / Flutter / React Native, and a webdimens.balanced(16) on the Web all describe the same idea.
This repository is the documentation hub. Each platform library ships from its own submodule with its own semver, install line, and changelog. The hub never pins versions — always confirm the install line in the submodule README you depend on.
Table of contents
- Platform repositories (quick reference)
- What is AppDimens?
- The problem it solves
- How AppDimens solves it
- Why AppDimens (advantages)
- When to use AppDimens (scenarios)
- The 14 scaling kernels at a glance
- Quick start (multi-stack)
- Platform matrix
- Hub vs submodules — who owns what
- Documentation map (
DOCS/) - Performance snapshot
- Comparison with alternatives
- FAQ
- Roadmap & status
- Contributing, security, license
- Author
What is AppDimens?
AppDimens is a multi-platform family of responsive sizing libraries. You write a single base value at the call-site — 16.sdp, balanced(16), webdimens.balanced(16) — and the library transforms it through an explicit, named kernel that reflects the current screen Configuration (width, height, aspect ratio, density, orientation, multi-window flags, fold state).
The hub publishes the shared vocabulary (BALANCED, DEFAULT, PERCENTAGE, …) and the mathematical reference for every kernel. Each platform repository (appdimens-dynamic, appdimens-sdps, appdimens-ssps, appdimens-ios, appdimens-dynamic-kmp, appdimens-flutter, appdimens-react-native, appdimens-web, appdimens-games) implements that vocabulary natively, so design tokens travel across stacks without translation.
Two operating tracks coexist:
- Runtime computation (
appdimens-dynamic, iOS, Flutter, RN, Web, KMP): a tiny kernel runs at call time, reading the liveConfigurationand producing aDp/ point / px value through the chosen strategy. Lock-free padded cache keeps hot-path cost at roughly 5 ns per hit on a Snapdragon 888, ~1 ns on JVM (see Performance snapshot). - Pre-computed resources (
appdimens-sdps,appdimens-ssps): thousands of pre-calculated@dimen/_*sdp,@dimen/_*ssp,_*hdp,_*wdpresources, ready to drop into XML — zero-runtime sizing for view systems and Compose alike.
You can — and many teams do — combine both.
The problem it solves
Modern UIs ship on a moving target. The same code base must look right on:
| Form factor | Typical width (dp / pt) | What "48 looks like" with raw dp/sp/pt |
|---|---|---|
| Watches | < 240 | 48 covers ~20% of the screen — too dominant |
| Small phones | 320–360 | ~14–15% — the calibrated baseline |
| Phablets / regular phones | 360–480 | 10–13% — already drifting |
| Small tablets | 600–720 | 6.7% — visibly cramped |
| Large tablets / foldables (open) | 720–960 | 5–6% — clearly undersized |
| TVs | 960–1920+ | 2.5–5% — practically invisible |
| Web / desktop viewports | 1024–3840+ | < 2% — broken |
dp / sp factor out physical density but not canvas extent, and they are blind to aspect ratio (a 4:3 tablet and a 21:9 phone receive the same number). Naïve linear scalers like SDP fix the smallness on tablets only to produce oversized UI on the same TVs.
Concretely, for a 48 dp button:
| Approach | Phone (360 dp) | Tablet (720 dp) | TV (1080 dp) | Verdict |
|---|---|---|---|---|
Raw dp / sp | 48 dp (13%) ✅ | 48 dp (6.7%) ❌ tiny | 48 dp (4.4%) ❌ invisible | Density-only |
| Linear SDP / SSP | 58 dp (16%) ✅ | 115 dp (16%) ❌ huge | 173 dp (16%) ❌ enormous | Over-scales |
AppDimens auto (BALANCED) | 58 dp (16%) ✅ | ~70 dp (10%) ✅ | ~85 dp (8%) ✅ | Calibrated everywhere |
The 720 dp / 1080 dp rows above are reproducible from DimenAutoDp (auto.md, hinge at 480 dp, ln gain 0.4).
How AppDimens solves it
flowchart LR concept["Hub concept<br/>(BALANCED · DEFAULT · PERCENTAGE · …)"] --> submodule["Submodule kernel<br/>(scaled · auto · percent · …)"] submodule --> token["Stack token<br/>(16.sdp · 16.asdp · balanced(16) · …)"] token --> output["Output Dp / Pt / Px<br/>(Configuration-aware)"]
Token sizing is modeled as a family of one-dimensional maps
f_S : (b, c) ↦ f_S(b, c)
where b is the design-time base (a dp / sp) and c is a snapshot of the runtime Configuration (post orientation/multi-window plumbing). S selects a kernel — scaled, auto, percent, power, logarithmic, fluid, interpolated, diagonal, perimeter, fit, fill, density, resize, or NONE.
Every kernel obeys four invariants (THEORY.md §1.2):
- Reference fixed point.
f_S(b, c₀) = bon the calibrated reference canvas — your design comp size is preserved on the reference device. - Monotone in canvas extent. Bigger canvas ⇒ never smaller output.
- Bounded growth. Output is sandwiched between linear and logarithmic envelopes — no runaway tablets/TVs.
- Aspect-ratio aware (opt-in). The optional
asuffix folds in an AR multiplier referenced to 16:9.
The verified constants (cross-checked against DesignScaleConstants.kt):
| Constant | Value | Meaning |
|---|---|---|
BASE_WIDTH_DP | 300f | Reference width denominator (matches the 300 dp design-comp tradition) |
BASE_HEIGHT_DP | 533f | Companion height baseline |
REFERENCE_ASPECT_RATIO | 1.78f | Neutral AR (16:9) — multiplier is 1 here |
| Diagonal baseline | √(300² + 533²) ≈ 611.63 dp | For diagonal kernel |
| Perimeter baseline | 833 dp | For perimeter kernel |
auto hinge | measured axis 480 dp | BALANCED switches from linear to log here |
auto ln gain | 0.4f | Log damping coefficient |
For the full math, see DOCS/THEORY.md and the canonical MATHEMATICS-AND-CALCULUS.md inside appdimens-dynamic.
Why AppDimens (advantages)
Each bullet below either points to a verifiable file in this repository or a measurable constant.
Engineering
- Explicit kernels per call-site. No surprise behaviour —
16.sdpis always thescaledkernel and16.asdpis always theautokernel. The Kotlin extension you write is the formula you read. (COMPOSE-API-CONVENTIONS.md) - Zero-XML option. Pure code-driven sizing via
appdimens-dynamic. Or pre-baked@dimenresources viaappdimens-sdps/appdimens-sspswhen you want XML tooling and zero-runtime cost. - Sub-microsecond hot path. Padded, sharded, lock-free cache. ~5 ns cache hit, ~2 ns raw multiply (Snapdragon 888 hardware capture, see
appdimens-dynamic/PERFORMANCE.md). - Foldable & multi-window aware. Effective-axis selection consults
WindowManagerfold state andisInMultiWindowMode. Both behaviours are opt-out per call via thei/iasuffixes (THEORY.md §3). - R8 / ProGuard ready. AARs ship
consumer-rules.proandres/raw/keep.xmlso apps can useminifyEnabled, R8 full mode (android.enableR8.fullMode=true), andshrinkResourceswithout extra rules. Seeappdimens-dynamic/R8-PROGUARD.md. - Test- and preview-friendly. Kernels are pure functions of
(base, Configuration)— works identically inside@Preview, unit tests, andBoxWithConstraints.
Design
- Perceptual scaling. Not just proportional — kernels like
auto,logarithmic,powerdamp growth on large canvases the way human visual perception expects (Weber–Fechner, Stevens). (THEORY.md §5) - Aspect-ratio compensation, opt-in. The
asuffix folds an AR multiplier referenced to 16:9. Elongated phones / foldables / wide TVs keep their visual weight without bespokerememberblocks. - Orientation inverters. Authored portrait but the device rotates? The
*Ph,*Lw,*Lhtoken families switch the driving axis automatically. (DOCS/ORIENTATION.md) - Physical units (mm / cm / inch). Real-world measurements where they matter (kiosks, AR, accessibility hit targets). (
physical-units.md)
Ecosystem
- Six platform tracks under one vocabulary — see Platform matrix. Android Compose + XML, Apple (UIKit + SwiftUI), Kotlin Multiplatform, Flutter, React Native, Web (vanilla / React / Vue / Svelte / Angular), and a games surface with Android NDK + iOS Metal.
- Compose 3.x package split. Each kernel is its own Gradle source package (
compose.scaled,compose.auto,compose.percent, …). You import what you use and nothing else — the binary footprint stays small.
Maintenance & honesty
- Every kernel is cited to a Kotlin file under
appdimens-dynamic/DOCUMENTATION/and a regression test underappdimens-dynamic/library/. - Hub theory is reproducible. Numerical comparisons in DOCS/THEORY.md §8 come from the same kernels you ship.
- No marketing-rank claims. The hub does not pretend a single global "best library" ranking. Categorical trade-offs vs other tools are discussed honestly in Comparison with alternatives.
When to use AppDimens (scenarios)
| Scenario | Why AppDimens helps | Suggested entry point |
|---|---|---|
| Multi-form-factor product (phones + tablets + foldables in one binary) | auto (BALANCED) keeps the same UI calibrated on a 360 dp phone and a 720 dp tablet, without the SDP overshoot | appdimens-dynamic quick start → tokens asdp / assp |
| TV / large-screen companion app | logarithmic and auto damp growth on canvases beyond 480 dp instead of inflating linearly | logarithmic.md · auto.md |
| Cross-platform design system | Same vocabulary on Android / iOS / KMP / Flutter / RN / Web — design tokens travel verbatim | DOCS/PLATFORMS.md |
| XML view system with breakpoint resources | @dimen/_16sdp, _18ssp, _300wdp, … shipped pre-computed; no runtime cost | appdimens-sdps · appdimens-ssps |
| Typography with hard min/max bounds | fluid clamps a typographic band (e.g. 16–24 sp between 320–768 dp) the same way CSS clamp() would, with optional AR | fluid.md |
| Game UI / HUD on arbitrary viewports | fit (letterbox) and fill (cover) keep the HUD intact across aspect ratios | fit.md · fill.md |
| Native game rendering (NDK / Metal) | Specialized modules with C++/NDK on Android (appdimens-games) and Metal on iOS | appdimens-games/ |
| Real-world physical sizing (kiosks, AR, accessibility targets) | mm / cm / inch helpers on every stack | physical-units.md |
| Rotation- / foldable-sensitive layouts | Base-orientation + *Ph / *Lw / *Lh inverters | DOCS/ORIENTATION.md |
| Container-fit titles / square widgets | resize builders (autoResizeTextSp, autoResizeSquareSize) pick the largest size in a min..max range that still fits | resize.md |
When AppDimens is overkill — single-form-factor prototypes with rigid hand-tuned mockups, or marketing microsites already handled by CSS
clamp()/ media queries.
The 14 scaling kernels at a glance
Sourced from appdimens-dynamic/DOCUMENTATION/ and cross-checked in DOCS/THEORY.md §5 and DOCS/PLATFORMS.md. Tokens shown are Compose 3.x; iOS / Flutter / RN / Web use builder names — see PLATFORMS.md.
| # | Kernel | Hub label | Compose token sketch | Primary use case | Reference |
|---|---|---|---|---|---|
| 1 | scaled | DEFAULT / FIXED | sdp, hdp, wdp, ssp, sem, sdpa | Phone-first SDP-style baseline (most common) | scaled.md |
| 2 | auto | BALANCED | asdp, ahdp, awdp, assp | Multi-device hybrid (linear under 480 dp, logarithmic above) | auto.md |
| 3 | percent | PERCENTAGE / DYNAMIC | psdp, phdp, pwdp, plus literal space* percentages | Axis-heavy / proportional containers and grids | percent.md |
| 4 | power | Stevens-style | pwsdp, pwssp | Configurable sublinear curve (exponent 0.6–0.9) | power.md |
| 5 | logarithmic | Weber–Fechner | logsdp, logssp | Maximum damping on TV / very large tablets | logarithmic.md |
| 6 | fluid | Clamp band | fsdp, fssp | Typography / spacing between explicit min/max | fluid.md |
| 7 | interpolated | Fixed–linear blend | isdp, issp | Moderate scaling (50% linear / 50% fixed) | interpolated.md |
| 8 | diagonal | Euclidean | dsdp, dssp | Scale by screen diagonal (true physical feel) | diagonal.md |
| 9 | perimeter | L¹ | psdp (perimeter package), pssp | Scale by W + H perimeter | perimeter.md |
| 10 | fit | Letterbox | fitsdp, fitssp | Game / canvas content that must not crop | fit.md |
| 11 | fill | Cover | fillsdp, fillssp | Game / canvas content that must fill | fill.md |
| 12 | density | DPI-bucket | densdp, denssp | Scale only when the dpi bucket changes | density.md |
| 13 | resize | Constraint geometry | autoResizeTextSp, autoResizeSquareSize, ResizeBound | Pick the largest size in a min..max range that fits | resize.md |
| 14 | physical units | Real-world | 10.mm, 8.cm, 5.inch | Real-world measurements (kiosks, AR, accessibility) | physical-units.md |
Plus a conceptual NONE (raw Dp / Sp) for surfaces that must stay constant.
Aspect-ratio suffix. Append
ato scaled / auto / interpolated / logarithmic / power tokens (16.sdpa,16.asdpa,16.sspa,16.assp) to fold in the AR multiplier described in THEORY.md §4. Appendi/iato opt out of the multi-window heuristic. Thefluidpackage exposes AR as an explicit builder parameter instead.
Quick start (multi-stack)
Install lines below are illustrative. The authoritative semver line for every artifact lives in the submodule README — click through before pinning.
Android — Jetpack Compose (appdimens-dynamic, production)
import com.appdimens.dynamic.compose.*
Box(
Modifier
.padding(16.sdp) // scaled — SDP-style baseline
.width(100.wdp) // scaled — width axis
.height(48.hdp) // scaled — height axis
) {
Text("Hello", fontSize = 16.ssp)
// For the hybrid BALANCED curve, use the `auto` tokens:
// padding(16.asdp), fontSize = 16.assp
}
→ appdimens-dynamic/README.md#quick-start--scaled-compose for full install line and AppDimensProvider setup.
Android — XML resources (appdimens-sdps + appdimens-ssps, production)
<TextView
android:layout_width="@dimen/_300sdp"
android:layout_height="wrap_content"
android:padding="@dimen/_16sdp"
android:textSize="@dimen/_18ssp"
android:text="Hello" />
→ appdimens-sdps/README.md · appdimens-ssps/README.md.
iOS — SwiftUI (appdimens-ios, work in progress)
Text("Hello")
.font(.system(size: AppDimens.shared.balanced(16).toPoints()))
.padding(AppDimens.shared.balanced(16).toPoints())
.frame(width: AppDimens.shared.balanced(300).toPoints())
→ appdimens-ios/ for current install status.
Kotlin Multiplatform (appdimens-dynamic-kmp, work in progress)
KMP test line publishes under the same Maven artifact ID; do not mix blindly with Android 3.1.x. The KMP track is aiming at its first stable 1.0.0 and is documented inside appdimens-dynamic-kmp/.
Flutter (appdimens-flutter, work in progress)
Container(
width: AppDimens.fixed(300).calculate(context),
padding: EdgeInsets.all(AppDimens.fixed(16).calculate(context)),
child: Text(
'Hello',
style: TextStyle(fontSize: AppDimens.fixed(16).calculate(context)),
),
)
React Native (appdimens-react-native, work in progress)
{% raw %}
const { balanced } = useAppDimens();
return (
<View style={{ padding: balanced(16) }}>
<Text style={{ fontSize: balanced(16) }}>Hello</Text>
</View>
);
{% endraw %}
Web — webdimens (work in progress)
import { webdimens } from 'webdimens';
document.getElementById('title')!.style.fontSize = webdimens.balanced(24);
document.getElementById('container')!.style.padding = webdimens.balanced(16);
→ appdimens-web/ for framework-specific (React / Vue / Svelte / Angular) hooks.
Platform matrix
Each folder below is its own Git submodule. Always confirm semver in the submodule README before pinning.
| Submodule | Platform | What it ships | Status | Illustrative coordinate |
|---|---|---|---|---|
appdimens-dynamic/ | Android (Compose, Kotlin, Java) | Runtime kernels — all 14 scaling modes (12 strategies + Resize + Physical units) | Production | io.github.bodenberg:appdimens-dynamic:3.1.5 |
appdimens-sdps/ | Android (XML, Compose, Kotlin, Java) | Pre-computed @dimen/_*sdp / _*hdp / _*wdp resources + Compose tokens | Production | io.github.bodenberg:appdimens-sdps:3.1.2 |
appdimens-ssps/ | Android (XML, Compose, Kotlin, Java) | Pre-computed @dimen/_*ssp text resources + Compose tokens | Production | io.github.bodenberg:appdimens-ssps:3.1.2 |
appdimens-games/ | Android (Kotlin + C++/NDK + OpenGL ES) | Specialized game-loop dimension types, Vector2D / Rectangle, viewport modes | Work in progress | io.github.bodenberg:appdimens-games:2.0.1 |
appdimens-ios/ | iOS / macOS (UIKit + SwiftUI + Metal) | AppDimens.shared.balanced(_) / defaultScaling(_) / smart(_) / fluid + Metal games | Work in progress | CocoaPods 2.0.0 / SPM (see submodule) |
appdimens-dynamic-kmp/ | Kotlin Multiplatform | Same vocabulary as appdimens-dynamic, multiplatform targets | Work in progress | Test line …appdimens-dynamic:4.0.0 — first KMP stable aimed at 1.0.0 |
appdimens-flutter/ | Flutter (Android / iOS / Web / desktop) | AppDimens.fixed(_), .dynamic(_), .fluidTo(_), .cm / .mm extensions | Work in progress | appdimens: ^2.0.0 |
appdimens-react-native/ | React Native (iOS / Android) | useAppDimens() hook with balanced / defaultScaling / smart / fluid | Work in progress | appdimens-react-native@2.0.0 |
appdimens-web/ | Web (vanilla / React / Vue / Svelte / Angular) | webdimens.balanced(_) + framework-specific hooks/services | Work in progress | webdimens@2.0.0 |
GitHub mirrors — dynamic · kmp · sdps · ssps · games · ios · flutter · react-native · web.
Clone with submodules
git clone --recurse-submodules https://github.com/bodenberg/appdimens.git
cd appdimens && git submodule update --init --recursive
Only need one stack? Prefer cloning the upstream repo for that artifact from the author's repositories instead of this umbrella.
Hub vs submodules — who owns what
flowchart LR Hub["appdimens hub<br/>(this repo)"] Hub --> AndroidGroup["Android"] Hub --> Apple["Apple / iOS"] Hub --> KMP["Kotlin Multiplatform"] Hub --> Flutter Hub --> RN["React Native"] Hub --> Web AndroidGroup --> dyn["appdimens-dynamic Production"] AndroidGroup --> sdps["appdimens-sdps Production"] AndroidGroup --> ssps["appdimens-ssps Production"] AndroidGroup --> games["appdimens-games WIP"] Apple --> ios["appdimens-ios WIP"] KMP --> kmpArtifact["appdimens-dynamic-kmp WIP"] Flutter --> flu["appdimens-flutter WIP"] RN --> rn["appdimens-react-native WIP"] Web --> webdimens["webdimens WIP"]
Important
Responsibility split
- Hub (
DOCS/+ this README) owns: shared vocabulary, mathematical theory, kernel taxonomy, cross-platform mapping, migration paths, hub-level FAQ. No pinned versions, ever. - Submodules own: source, semver, Gradle / npm / pod / pub install lines, R8/ProGuard rules, per-API changelogs, code-level docs, regression tests.
When prose in the hub disagrees with the submodule, the submodule is the source of truth.
Runtime dynamic vs baked sdps / ssps on Android
appdimens-dynamic | appdimens-sdps / appdimens-ssps | |
|---|---|---|
| Computation | Runtime from live Configuration | Pre-computed res/values-sw*/dimens.xml buckets |
| Flexibility | All 14 kernels, per-call AR / inverter / qualifier flags | One curve per artifact, @dimen friendly |
| Cost | Tiny AAR; ~5 ns cache hit, ~2 ns no-AR multiply | Larger resource tables, zero runtime |
| XML integration | Only via Compose / code package | First-class @dimen/_16sdp etc. |
Many teams mix both: SDP/SSP for XML layouts, appdimens-dynamic for Compose / Kotlin-side dimensions. Full taxonomy of when to pick which: DOCS/THEORY.md and DOCS/GUIDE.md.
Documentation map (DOCS/)
The DOCS/ folder is theory-only — concepts, math, cross-platform mapping, migration. Choose your learning path:
| Goal | Read | Then |
|---|---|---|
| I want to ship today | DOCS/GUIDE.md — strategy decision tree, FAQs, common patterns | Submodule README for your stack |
| I want to understand the math | DOCS/THEORY.md — formal kernels, axioms, comparisons | MATHEMATICS-AND-CALCULUS.md |
| I'm migrating from 1.x / 2.x / SDP–SSP | DOCS/MIGRATION.md — legacy .fxdp / .dydp / unified DSL → Compose 3.x packages | The submodule changelog you ship |
| I'm porting across stacks | DOCS/PLATFORMS.md — concept ↔ submodule API, verified constants | The matching submodule README |
| I rotate / foldable my UI | DOCS/ORIENTATION.md — base orientation, *Ph / *Lw / *Lh inverters | COMPOSE-API-CONVENTIONS.md |
| I want copy-paste recipes | DOCS/EXAMPLES.md — long-form snippets per stack | The submodule's app/ sample where available |
Visual & interactive resources
Performance snapshot
Numbers captured on Xiaomi 2107113SG (Snapdragon 888 · Android 14) physical hardware, debug build without minify. Full methodology, R8 deltas, and per-device variability discussed in appdimens-dynamic/PERFORMANCE.md.
| Operation | Result | Notes |
|---|---|---|
| Raw math, no AR | ~2 ns | SCALED / AUTO / FLUID / PERCENT fast-bypass path (cache is intentionally skipped — a 2 ns multiply is cheaper than the ~5 ns hash) |
| Raw math with AR | ~45 ns | ln() evaluation on hardware |
| Cache hit (no AR) | ~5 ns | Lock-free padded sharded cache lookup |
| Cache hit (with AR) | ~35 ns | Zero-math path for AR kernels |
| Batch resolution (100 items) | ~169 ns | getBatch() API, SIMD-friendly loop |
| Persistence load (100 entries) | 0.76 ms | Cold start from disk-persisted cache |
| JVM cache hit (local) | ~1 ns | Linux + JVM 17 |
| Real-world (1 000-item Compose scroll) | ~996 ms total / ~996 µs per item | Indistinguishable from baseline; 0% jank at 120 FPS |
With R8 + minify on release builds, the dashboard-style harness drops further (~125–155 ns micro combined, ~367–380 ns per-item macro). See the Build variants & R8 note at the top of PERFORMANCE.md.
Comparison with alternatives
The hub does not publish a single global "score / 100" ranking — comparisons depend heavily on form-factor mix, design philosophy, and what you measure. Instead, here are the honest categorical trade-offs. Quantitative kernel comparisons live in DOCS/THEORY.md §8–10.
| Approach | What it does well | What AppDimens adds |
|---|---|---|
Raw dp / sp / pt / px | Zero deps, predictable on the calibrated device | Calibration across canvas extent and aspect ratio, not just density |
Linear SDP / SSP (e.g. Intuit sdp-android) | Pre-computed @dimen resources, XML-native | Same baked resources (appdimens-sdps/-ssps) plus non-linear kernels (auto, logarithmic, power, fluid) — and you can mix runtime computation in Compose |
CSS vw / vh / clamp() / container queries | First-class in modern browsers, no JS | A single vocabulary that travels off the Web (iOS / Android / Flutter / RN) — appdimens-web integrates clamp()-style behaviour as the fluid kernel |
ScreenUtil / size-matters / similar libraries | Single dependency, friendly API | Strategy-per-call-site instead of a single global curve; foldable + multi-window heuristics; AR compensation; reproducible math doc per kernel |
If you are already happy with one of the above on a phone-only product, AppDimens may be overkill — see GUIDE.md "Fast path / When AppDimens is overkill".
FAQ
Which strategy should I reach for first?
auto (BALANCED) for multi-device, scaled for phone-first / SDP-style, percent for axis-heavy containers. Full decision tree: DOCS/GUIDE.md "Fast path".
Will this break my existing SDP / SSP layouts?
No. appdimens-sdps / appdimens-ssps ship the canonical SDP/SSP resource tables (@dimen/_16sdp, …) so existing XML keeps working. You can adopt the runtime appdimens-dynamic kernels gradually inside Compose. Migration story: DOCS/MIGRATION.md.
Does it work in pure XML layouts?
Yes — appdimens-sdps and appdimens-ssps are XML-native (@dimen/_16sdp, @dimen/_18ssp, …). For runtime kernels, appdimens-dynamic exposes a code package for Views and a compose package for Compose.
Does it work inside @Preview / unit tests?
Yes. Every kernel is a pure function of (base, Configuration). Compose previews resolve as on a regular device — and you can override LocalConfiguration to simulate any canvas.
Will rotation / foldables break my proportions?
By design no. Effective-axis selection consults Configuration and WindowManager fold state. For authored portrait → device landscape (or vice versa), use the *Ph / *Lw / *Lh inverter tokens. See DOCS/ORIENTATION.md.
Is the cache thread-safe?
Yes. It is a lock-free padded sharded cache (128-byte shards to avoid false sharing on ARM64) with bypass for the simplest no-AR multiplies. Details in appdimens-dynamic/PERFORMANCE.md.
Can I keep some sizes truly constant?
Yes — use raw Dp / Sp (or .dp / .sp Compose extensions) for icons that must stay 24 dp everywhere. The conceptual NONE kernel is exactly this.
What changed since 2.x?
On Compose, the old unified DSL (.fxdp, .dydp, .balanced().dp) was split into strategy packages (compose.scaled, compose.auto, compose.percent, …). Naming rename Fixed → DEFAULT, Dynamic → PERCENTAGE is purely narrative; Gradle uses scaled and percent. iOS / Flutter / RN / Web keep their builder names. Full mapping: DOCS/MIGRATION.md.
Roadmap & status
- ✅ Production:
appdimens-dynamic,appdimens-sdps,appdimens-ssps(Android). - 🔄 Work in progress:
appdimens-ios,appdimens-dynamic-kmp(first stable aimed at1.0.0),appdimens-flutter,appdimens-react-native,appdimens-web,appdimens-games. - 🧪 Hub theory: kernel taxonomy and verified constants are stable; benchmark deltas continue to track new device classes (
PERFORMANCE.md).
Issues about this hub repo (typos, dead links, missing concept docs) → Hub issues. Shipping bugs (compile errors, wrong numbers, build problems) belong in the submodule repository you depend on so they reach the maintainers and CI of that artifact.
Contributing, security, license
- CONTRIBUTING.md — how to propose hub or submodule changes, doc style, PR checklist.
- SECURITY.md — responsible disclosure channel for vulnerabilities.
- CODE_OF_CONDUCT.md — community expectations.
- CHANGELOG.md — high-level coordinated-release history; each submodule maintains its own detailed changelog.
- LICENSE — Apache 2.0.
Author
Jean Bodenberg — @bodenberg · appdimens-project.web.app
If AppDimens helps your project, please ⭐ this repo and the submodules you use — visibility is what funds further work.
📚 DOCS · 📘 GUIDE · 📐 THEORY · 💡 EXAMPLES · 🧭 PLATFORMS · ♻️ MIGRATION · 🔄 ORIENTATION