Skip to content
All Libraries

KMP Splash

A Gradle plugin that automates the entire native splash screen setup for both Android and iOS from a single config block.

GitHub
version 0.3.0 Compose Multiplatform Apache 2.0 Maven Central

Read the story behind it: How I Stopped Opening Xcode for Splash Screens →

On this page

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:

MethodExampleNotes
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.whiteConvenience constant
SplashColor.blackConvenience constant

backgroundColorNight is optional. If omitted, the light color is used for both modes.

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: UILaunchScreen requires 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.
Maintained by KMP Bits View source on GitHub →