Bodenberg.AppDimens.Sdps

August 22, 2026 · View on GitHub

.NET 10 binding for Android (net10.0-android) that wraps AppDimens SDPS — responsive layout (SDP / HDP / WDP) and typography (SSP / HSP / WSP) in one library, backed by thousands of pre-generated @dimen resources, plus imperative APIs, conditional facilitators, aspect-ratio variants, accessibility text modes, and foldable-aware overloads.

Kotlin/Java sources, XML naming, and Android-focused guides live upstream:

bodenberg/appdimens-sdps

Maven artifact embedded in this package: io.github.bodenberg:appdimens-sdps 3.1.7.


Install

dotnet add package Bodenberg.AppDimens.Sdps --version 3.6.0

Pin a version explicitly when you rely on a specific package revision (see Package version vs embedded AAR below).


Requirements

RequirementNotes
Target frameworknet10.0-android (.NET for Android / .NET MAUI Android)
Minimum Android API24 (matches the packaged AAR)
WorkloadAndroid (dotnet workload install android) or MAUI
JDK17 or 21 for the Xamarin.Android toolchain on .NET 10

Use Android SDK platform 36+ (or MSBuild InstallAndroidDependencies) when building bindings locally on .NET 10.

The AAR bundles values-sw* / values-w* / values-h* dimen XML (sizes 1–600) for both dp and sp buckets.


What this library provides

CapabilitySummary
SDP / HDP / WDPScale margins, padding, sizes by smallest width, height, or width
SSP / HSP / WSPScale text on the same three axes
SEM / HEM / WEMTypography curves that ignore system font scale
XML @dimene.g. @dimen/_16sdp, @dimen/_32hsp — zero-config in layouts
Code APIDimenSdp / DimenSsp → pixel values for Views, custom drawing, MAUI
Aspect ratioSdpa, Sspa, … — geometry multiplier on top of the XML bucket
Multi-windowSdpi, Sspia, … — parity with Dynamic “ignore scaling” paths
InvertersSdpPh, HspLw, WdpLh, … — orientation-aware axis switch
FacilitatorsRotate, Mode, Qualifier, Screen (+ Plain px variants for dp)
BuildersDimenScaled (layout) and ScaledSp (text) — priority-based rule lists
Physical unitsDimenPhysicalUnits — mm / cm / inch helpers
PrefetchWarmupSdpsFactors — optional aspect-ratio factor warmup

SDPS is the all-in-one responsive dimen package (layout + type). Use AppDimens SSPS if you only need typography, or AppDimens Dynamic for code-only multi-strategy scaling without XML grids.


C# namespaces (binding layout)

Public Kotlin @JvmStatic APIs appear under Com.Appdimens.Sdps.*:

AreaNamespace / types
Views / imperative (recommended)Com.Appdimens.Sdps.Code
Layout (dp)DimenSdp, DimenScaled, CustomDpEntry
Typography (sp)DimenSsp, ScaledSp, CustomSpEntry
Physical unitsDimenPhysicalUnits
ExtensionsDimenExtensionsKt, DimenSspExtensionsKt, DimenSspScaledKt
Shared enumsCom.Appdimens.Sdps.CommonDpQualifier, Inverter, Orientation, UiModeType, UnitType
AR factorsCom.Appdimens.Sdps.CoreAppDimensSdpsFactors
Compose (limited)Com.Appdimens.Sdps.Compose.* — see Jetpack Compose below

Foldable overloads accept AndroidX.Window.Layout.IFoldingFeature from Xamarin.AndroidX.Window.


Quick start (Activity / Views)

using Android.App;
using Android.OS;
using Com.Appdimens.Sdps.Code;

[Activity(Label = "My App", MainLauncher = true)]
public class MainActivity : Activity
{
    protected override void OnCreate(Bundle? savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        DimenSdp.WarmupSdpsFactors(this);

        float paddingPx = DimenSdp.Sdp(this, 16);
        float cardHeight  = DimenSdp.Hdp(this, 120);
        float bannerWidth = DimenSdp.Wdp(this, 200);

        float titlePx = DimenSsp.Ssp(this, 20);
        float bodyPx  = DimenSsp.Ssp(this, 14);
    }
}

Apply paddingPx / titlePx as pixel sizes on View layout params or TextView.TextSize.


Layout dimensions (DimenSdp)

All methods return pixels (float) for a nominal dp integer (e.g. 16_16sdp resource bucket).

Primary axes

Method familyScales by
Sdp / Sdpa / Sdpi / SdpiaSmallest width (+ AR / multi-window)
Hdp / Hdpa / …Screen height
Wdp / Wdpa / …Screen width

Inverter shortcuts (orientation-aware)

ExampleTypical behaviour
SdpPh / SdpPhaSmallest width → height in portrait
SdpLw / SdpLwaSmallest width → width in landscape
HdpLw / HdpLwaHeight → width in landscape
WdpLh / WdpLhaWidth → height in landscape

Each base method has matching a / i / ia variants where applicable.

Resource IDs (XML or GetDimension)

int padRes = DimenSdp.SdpRes(this, 16);
float padPx = Resources!.GetDimension(padRes);

// Or generic qualifier path:
int resId = DimenSdp.GetResourceId(this,
    Com.Appdimens.Sdps.Common.DpQualifier.SmallWidth, 16,
    Com.Appdimens.Sdps.Common.Inverter.None);

float px = DimenSdp.GetDimensionInPx(this,
    Com.Appdimens.Sdps.Common.DpQualifier.SmallWidth, 16,
    Com.Appdimens.Sdps.Common.Inverter.None,
    ignoreFontScale: false);

*Res helpers exist for inverter variants (SdpPhRes, HdpLwRes, …).

Facilitators (conditional layout)

using Com.Appdimens.Sdps.Code;
using Com.Appdimens.Sdps.Common;

float pad = DimenSdp.SdpRotate(this, 16, 24);
float padLandscape = DimenSdp.SdpRotate(this, 16, 24, Orientation.Landscape);

// Already-resolved px values (no second resource pass):
float plain = DimenSdp.SdpRotatePlain(this, 48f, 72f, Orientation.Landscape);

float tvPad = DimenSdp.SdpMode(this, 16, 24, UiModeType.Television);
float tablet = DimenSdp.SdpQualifier(this, 16, 20, DpQualifier.SmallWidth, 600);
float fold = DimenSdp.SdpScreen(this, 16, 28,
    UiModeType.Television, DpQualifier.SmallWidth, 600);

HdpRotate, WdpMode, HdpScreen, etc. mirror the HDP / WDP families.

DimenScaled builder (layout)

Priority-ordered rules — first match wins (not the same as nested extension order):

var chain = DimenSdp.Scaled(16)
    .Screen(UiModeType.Television, DpQualifier.SmallWidth, 600, 40)
    .Screen(UiModeType.Television, 32)
    .Screen(Orientation.Landscape, 20);

float px = chain.Sdp(this);
float heightPx = chain.Hdp(this);

Explore generated Screen(...) overloads on DimenScaled for qualifiers, inverters, and foldables.


Typography (DimenSsp)

Same conceptual model as layout, but for sp buckets (_16ssp, _32hsp, …).

Primary axes

MethodScales by
Ssp / Sspa / Sspi / SspiaSmallest width
Hsp / Hspa / …Height
Wsp / Wspa / …Width

Accessibility (ignore font scale)

MethodUse when
Sem / Sema / …Smallest-width curve, fixed vs user font scale
Hem / Hema / …Height axis, fixed scale
Wem / Wema / …Width axis, fixed scale

Resource IDs

int textRes = DimenSsp.SspRes(this, 16);
float textPx = DimenSsp.Ssp(this, 16);

float lowLevel = DimenSsp.GetDimensionInSpPx(this,
    DpQualifier.SmallWidth, 16, Inverter.None, ignoreFontScale: false);

Facilitators & ScaledSp builder

float rotated = DimenSsp.SspRotate(this, 16, 24, ignoreFontScale: false);
float plain = DimenSsp.SspRotatePlain(this, 42f, 56f, Orientation.Landscape);

var textChain = DimenSsp.Scaled(16)
    .Screen(UiModeType.Television, DpQualifier.SmallWidth, 600, 40)
    .Screen(Orientation.Landscape, 20);

float titlePx = textChain.Ssp(this);
float fixedPx = textChain.Sem(this);   // ignore font scale

HspRotate, WspMode, SspScreen, etc. complete the HSP / WSP surface.


XML layouts (bundled resources)

Use dimens directly in Android XML / MAUI Android layouts:

<LinearLayout
    android:padding="@dimen/_16sdp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="@dimen/_200wdp"
        android:layout_height="@dimen/_48hdp"
        android:textSize="@dimen/_18ssp"
        android:lineSpacingExtra="@dimen/_4ssp" />
</LinearLayout>

Naming pattern: _<n>sdp, _<n>hdp, _<n>wdp, _<n>ssp, _<n>hsp, _<n>wsp (and sem / hem / wem variants where generated). Values 1–600 are pre-calculated per qualifier bucket inside the AAR.


Aspect ratio & warmup

Sdpa, Sspa, Hdpa, … apply an aspect-ratio multiplier on top of the XML-resolved size (aligned with appdimens-dynamic when the same bucket is selected).

DimenSdp.WarmupSdpsFactors(this);

float layout = DimenSdp.Sdp(this, 32);
float layoutAr = DimenSdp.Sdpa(this, 32);

float text = DimenSsp.Ssp(this, 16);
float textAr = DimenSsp.Sspa(this, 16);

Factors live in Com.Appdimens.Sdps.Core.AppDimensSdpsFactors and invalidate when screen geometry or density changes.


Physical units

Com.Appdimens.Sdps.Code.DimenPhysicalUnits converts real-world units using display metrics:

float dpFromMm = DimenPhysicalUnits.ToDpFromMm(10f, Resources);
float pxFromCm = DimenPhysicalUnits.ToPxFromCm(2f, Resources);
float spFromInch = DimenPhysicalUnits.ToSpFromInch(0.25f, Resources);

Also: unit conversions (MmToCm, InchToMm, …) and geometry helpers (RadiusFromDiameter, …).


Shared types (Com.Appdimens.Sdps.Common)

TypePurpose
DpQualifierSmallWidth, Width, Height, …
DpQualifierEntryQualifier + threshold for builders
InverterAxis inversion for low-level resolution
OrientationPortrait / landscape facilitators
UiModeTypeTV, automotive, watch, …
UnitTypePhysical unit enums

Custom entries

CustomDpEntry and CustomSpEntry (in Com.Appdimens.Sdps.Code) support advanced builder/custom bucket scenarios exposed by the upstream library. Inspect generated members or upstream docs when you outgrow static Sdp/Ssp helpers.


Jetpack Compose (com.appdimens.sdps.compose)

The AAR includes Compose extensions (16.sdp, 18.ssp, scaledSp(), facilitators, …) that require androidx.compose.runtime.Composer. With the current class-parse binding pipeline, usable C# wrappers for most Compose helpers are not generated.

Recommended for .NET:

  • Com.Appdimens.Sdps.Code — Activities, Fragments, custom views, MAUI Android handlers
  • XML @dimen/_Nsdp / _@dimen/_Nssp in layout resources
  • DimenScaled / DimenSsp.Scaled builders from C#

Dependencies brought in by this package

NuGetRole
Xamarin.Kotlin.StdLibKotlin runtime
Xamarin.AndroidX.CoreCore / resources
Xamarin.AndroidX.WindowFoldables (FoldingFeature)
Xamarin.AndroidX.Lifecycle.RuntimeLifecycle alignment with upstream AAR

Package version vs embedded AAR

LayerVersion
Maven / embedded .aarappdimens-sdps 3.1.7
NuGet3.6.0net10.0-android and updated Xamarin AndroidX; Android binary 3.1.7

When Maven publishes a new version, run ./scripts/sync-aar-from-maven.sh <maven-version> and bump the NuGet version accordingly.


Build this binding locally

cd appdimens-sdps-net-binding
dotnet build AppDimens.Sdps.sln -c Release

Smoke test: AppDimens.Sdps.SmokeTest — produce an APK with:

dotnet publish AppDimens.Sdps.SmokeTest/AppDimens.Sdps.SmokeTest.csproj -c Release -f net10.0-android -p:AndroidPackageFormat=apk

Sync the upstream AAR:

./scripts/sync-aar-from-maven.sh 3.1.7

PackageFocus
Bodenberg.AppDimens.SspsTypography only (SSP/HSP/WSP) — smaller dependency if you do not need sdp/hdp/wdp XML
Bodenberg.AppDimens.DynamicCode-only scaling — 15 strategies, no pre-built @dimen grids

ResourceURL
AppDimens (main project — NuGet Project website)https://github.com/bodenberg/appdimens
Android library (NuGet Source repository; implementation & issues)https://github.com/bodenberg/appdimens-sdps
Maven Centralhttps://central.sonatype.com/artifact/io.github.bodenberg/appdimens-sdps
.NET binding monorepohttps://github.com/bodenberg/appdimens-net-binding

License

Apache 2.0, consistent with the upstream library.