Build Consistent Cross-Platform UIs
Theming is the secret sauce for creating polished, professional apps. With Compose Multiplatform, you can define a unified design system that adapts to Android, iOS, desktop, and web—while still allowing platform-specific tweaks. This guide covers Material Design theming, dark mode, and adaptive styling strategies for KMP apps.
Compose Multiplatform uses Material Design 3 by default, ensuring consistency across platforms.
@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
MaterialTheme(
colorScheme = lightColorScheme(), // Default M3 colors
typography = Typography(),
shapes = Shapes(),
content = content
)
}
// Usage
@Composable
fun App() {
MyAppTheme {
HomeScreen()
}
}
Define light/dark palettes for brand consistency:
private val LightColors = lightColorScheme(
primary = Color(0xFF6200EA), // Purple
secondary = Color(0xFF03DAC6), // Teal
background = Color.White
)
private val DarkColors = darkColorScheme(
primary = Color(0xFFBB86FC), // Light purple
secondary = Color(0xFF03DAC6),
background = Color(0xFF121212) // Dark gray
)
@Composable
fun MyAppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colors = if (darkTheme) DarkColors else LightColors
MaterialTheme(colorScheme = colors, /*...*/)
}
Pro Tip: Use isSystemInDarkTheme()
for automatic dark/light switching.
Adjust designs for iOS, Android, or desktop without breaking shared logic.
import org.jetbrains.compose.ui.platform.Platform
val isAndroid = Platform.OS == "Android"
val isIOS = Platform.OS == "iOS"
@Composable
fun PlatformButton(label: String) {
val color = when (Platform.OS) {
"Android" -> Color.Blue
"iOS" -> Color.Gray
else -> MaterialTheme.colorScheme.primary
}
Button(colors = ButtonDefaults.buttonColors(color)) {
Text(label)
}
}
val AppTypography = Typography(
headlineLarge = TextStyle(
fontSize = 30.sp,
fontWeight = FontWeight.Bold
),
bodyMedium = TextStyle(fontSize = 16.sp)
)
// Usage
Text("Title", style = MaterialTheme.typography.headlineLarge)
val AppShapes = Shapes(
small = RoundedCornerShape(4.dp), // Buttons
medium = RoundedCornerShape(8.dp), // Cards
large = RoundedCornerShape(16.dp) // Dialogs
)
Keep styles consistent with a theme manager:
object ThemeManager {
val colors: ColorScheme
get() = if (isSystemInDarkTheme()) DarkColors else LightColors
val typography: Typography = AppTypography
val shapes: Shapes = AppShapes
}
// Apply everywhere
MaterialTheme(
colorScheme = ThemeManager.colors,
typography = ThemeManager.typography,
shapes = ThemeManager.shapes
)
isSystemInDarkTheme()
.Platform.OS
checks for platform-specific tweaks.Introduction: Transform Your Cross-Platform Development with Material Design 3 Are you ready to revolutionize your… Read More
Jetpack Compose 1.8 rolls out handy features like Autofill integration, slick Text enhancements including auto-sizing… Read More
Reified Keyword in Kotlin: Simplify Your Generic Functions Kotlin's reified keyword lets your generic functions know the… Read More
Android Studio Cloud: Ditch the Setup, Code Anywhere (Seriously!) Alright, fellow Android devs, gather 'round… Read More