Overview
KMP Splash handles the entire splash screen setup for both Android and iOS from a single Gradle config block. No Xcode, no storyboards, no manual asset catalogs.
On Android, it uses the Core Splashscreen API to render a native launch screen and optionally extend it until your app is ready.
On iOS, it generates a UILaunchScreen plist entry (iOS 14+) and provides a Compose layer that bridges the gap between the native launch screen and your first composable — eliminating the white flash on cold start.
Both platforms read the same config. You define your colors and logo once.
Installation
1. Apply the plugin
In your composeApp/build.gradle.kts, apply the plugin and add the runtime dependency:
plugins {
id("io.github.kmpbits.splash") version "1.0.0"
}
2. Add the runtime dependency
commonMain.dependencies {
implementation("io.github.kmpbits:splash-runtime:1.0.0")
}
3. Sync
Run a Gradle sync. The plugin registers two tasks — generateAndroidSplash and generateIosSplash — which run automatically before compilation.
Configuration
Add a splashScreen block anywhere in your composeApp/build.gradle.kts:
splashScreen {
backgroundColor = SplashColor.hex("#FFFFFF")
backgroundColorNight = SplashColor.hex("#1A1A2E") // optional
logo = SplashLogo.resource("logo.png")
logoDark = SplashLogo.resource("logo_dark.png") // optional
}
SplashColor
Defines the splash background color. Three factory methods are available:
| Method | Example | Notes |
|---|---|---|
SplashColor.hex(value) | SplashColor.hex("#FFFFFF") | Validates format at config time |
SplashColor.rgb(r, g, b) | SplashColor.rgb(26, 26, 46) | Integer values 0–255 |
SplashColor.white | — | Convenience constant |
SplashColor.black | — | Convenience constant |
backgroundColorNight is optional. If omitted, the light color is used for both modes.
SplashLogo
Defines the logo image. The resource() factory resolves the file from composeResources/drawable/ automatically — you only supply the filename.
logo = SplashLogo.resource("logo.png")
logoDark is optional. If omitted, the light logo is used for both modes.
Android Setup
Extend SplashActivity in your MainActivity. Override isReady() to hold the splash until your app has finished loading, and onFinished() to hand off to your Compose UI:
// androidMain/MainActivity.kt
class MainActivity : SplashActivity() {
override suspend fun isReady(): Boolean {
// Load data, check auth state, warm up caches, etc.
delay(1000)
return true
}
override fun onFinished() {
setContent { App() }
}
}
isReady() runs on a background coroutine. Return true when the app is ready to show. The splash stays visible until you do.
The plugin generates themes.xml and patches AndroidManifest.xml automatically. No manual theme wiring required.
Edge to Edge
If you need to call enableEdgeToEdge(), override onPreCreate() instead of onCreate(). This hook runs at exactly the right moment — after installSplashScreen() but before super.onCreate() — which is the order Android requires:
class MainActivity : SplashActivity() {
override fun onPreCreate() {
enableEdgeToEdge()
}
override suspend fun isReady(): Boolean { ... }
override fun onFinished() { ... }
}
iOS Setup
Call SplashConfig from your MainViewController and swap it out once the app is ready:
// iosMain/MainViewController.kt
fun MainViewController() = ComposeUIViewController {
SplashConfig(
isReady = {
delay(1500) // Your initialization logic
true
}
) {
App()
}
}
SplashConfig renders a Compose screen that is visually identical to the native launch screen — same background color, same logo. It holds that screen until isReady returns true, then calls onFinished.
The colors and logo are read from your Gradle config automatically. You don’t pass them at the call site.
The plugin generates the UILaunchScreen plist entry and adds the required asset catalog entries. No Xcode required.
Dark Mode
Both backgroundColorNight and logoDark in the config block are optional.
If you provide them, the plugin generates separate dark-mode assets for Android (themes-night.xml) and the appropriate asset catalog entries for iOS.
If you omit them, the light values are used for both modes.
System vs. app dark mode
The native launch screen reads the system dark mode setting, not your app’s preference. If your app has its own appearance toggle and the user has set it to dark while the device is in light mode, the native splash will still render in light mode.
This is an OS-level limitation — the native splash runs before any app code. The Compose layer (SplashConfig on iOS, the extended splash on Android) corrects to your app’s preference immediately after.
For most apps this is not noticeable. If it matters, use a background color that works in both modes.
Known Limitations
- Minimum iOS version:
UILaunchScreenrequires iOS 14+. Projects targeting iOS 13 or earlier are not supported. - System dark mode only: The native splash cannot respond to app-level appearance overrides. See Dark Mode above.
- PNG logos only: The logo file must be a PNG. SVG is not supported by the iOS asset catalog pipeline.