Android Design Tokens
Android Design Tokens
Android design tokens bring systematic design value management to Android application development. Implementing tokens on Android requires understanding platform-specific formats, resource systems, and the differences between View-based and Compose-based approaches. Effective Android token implementation enables consistent styling while maintaining native platform idioms.
What Are Android Design Tokens
Android design tokens are design values stored in formats that Android applications can consume. For traditional View-based development, this means XML resource files. For Jetpack Compose, this means Kotlin objects or functions providing typed values.
Token transformation pipelines generate these Android-specific outputs from platform-agnostic token definitions. A single token source produces both XML resources and Kotlin code, depending on the target UI framework.
How Android Design Tokens Work
Traditional Android development uses XML resources for design values. Token pipelines generate files in the res/values directory structure:
Colors in colors.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="color_primary">#FF3B82F6</color>
<color name="color_background_default">#FFFFFFFF</color>
<color name="color_text_primary">#FF171717</color>
</resources>
Dimensions in dimens.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="spacing_sm">8dp</dimen>
<dimen name="spacing_md">16dp</dimen>
<dimen name="spacing_lg">24dp</dimen>
<dimen name="font_size_body">16sp</dimen>
</resources>
Applications reference these resources:
<Button
android:background="@color/color_primary"
android:padding="@dimen/spacing_md"
android:textSize="@dimen/font_size_body" />
Jetpack Compose uses Kotlin objects for type-safe token access:
object Tokens {
object Color {
val Primary = Color(0xFF3B82F6)
val BackgroundDefault = Color(0xFFFFFFFF)
val TextPrimary = Color(0xFF171717)
}
object Spacing {
val Sm = 8.dp
val Md = 16.dp
val Lg = 24.dp
}
}
Compose components reference tokens directly:
Button(
modifier = Modifier.padding(Tokens.Spacing.Md),
colors = ButtonDefaults.buttonColors(
containerColor = Tokens.Color.Primary
)
) {
Text(text = "Click me")
}
Key Considerations
- Android uses ARGB format with alpha first (FF prefix for opaque colors)
- Dimension values should use dp for spacing and sp for text
- XML resource names use snake_case by convention
- Compose tokens benefit from Kotlin’s type safety
- Theme overlays enable runtime token changes in View system
- MaterialTheme provides Compose theming infrastructure
- Configuration qualifiers enable responsive and accessibility variants
- Token updates require app recompilation
Common Questions
How should theming work on Android?
Android theming differs between View and Compose frameworks.
View-based theming uses theme overlays and style attributes. Tokens map to theme attributes rather than direct resource references:
<style name="Theme.App" parent="Theme.MaterialComponents.Light">
<item name="colorPrimary">@color/color_primary</item>
<item name="colorSurface">@color/color_background_default</item>
</style>
<style name="Theme.App.Dark" parent="Theme.MaterialComponents.Dark">
<item name="colorPrimary">@color/color_primary_dark</item>
<item name="colorSurface">@color/color_background_dark</item>
</style>
Compose theming uses MaterialTheme or custom composition locals:
@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = if (darkTheme) {
darkColorScheme(
primary = Tokens.Color.PrimaryDark,
surface = Tokens.Color.BackgroundDark
)
} else {
lightColorScheme(
primary = Tokens.Color.Primary,
surface = Tokens.Color.BackgroundDefault
)
}
MaterialTheme(
colorScheme = colorScheme,
content = content
)
}
Compose’s composition-based theming is more flexible than View themes, enabling fine-grained customization.
How do tokens integrate with Material Design?
Android applications often use Material Design components, which have their own theming systems.
Material Components (View) expect tokens mapped to material theme attributes:
<item name="colorPrimary">@color/color_primary</item>
<item name="colorOnPrimary">@color/color_text_on_primary</item>
<item name="colorSurface">@color/color_background_surface</item>
This mapping bridges design system tokens with Material’s attribute expectations.
Material 3 (Compose) uses a color scheme structure:
val colorScheme = lightColorScheme(
primary = Tokens.Color.Primary,
onPrimary = Tokens.Color.OnPrimary,
primaryContainer = Tokens.Color.PrimaryContainer,
// ... additional Material 3 roles
)
Design system tokens may not align perfectly with Material’s semantic structure. Bridge layers can map between design system semantics and Material semantics.
Some organizations bypass Material theming entirely, applying tokens directly to components without using Material’s theme infrastructure.
How should token pipelines generate Android outputs?
Style Dictionary configuration for Android:
{
platforms: {
android: {
transformGroup: 'android',
buildPath: 'android/app/src/main/res/values/',
files: [
{
destination: 'colors.xml',
format: 'android/colors',
filter: { type: 'color' }
},
{
destination: 'dimens.xml',
format: 'android/dimens',
filter: { type: 'dimension' }
}
]
},
compose: {
transformGroup: 'compose',
buildPath: 'android/app/src/main/kotlin/tokens/',
files: [{
destination: 'Tokens.kt',
format: 'compose/object',
className: 'Tokens'
}]
}
}
}
Custom formats may be needed for organization-specific structures or composite tokens like typography that bundle multiple values.
Build integration ensures token generation runs before Android compilation. Gradle tasks can invoke token build scripts:
task generateTokens(type: Exec) {
commandLine 'npm', 'run', 'build-tokens'
}
preBuild.dependsOn generateTokens
Summary
Android design tokens enable consistent design value usage through XML resources for View-based development and Kotlin objects for Compose. Token pipelines transform platform-agnostic definitions into Android-specific formats. Integration with Material Design components requires mapping between design system tokens and Material’s theming structure. Build automation ensures token generation stays synchronized with application development.
Buoy scans your codebase for design system inconsistencies before they ship
Detect Design Drift Free