Splash Screen in .NET MAUI 10: Custom Animations, Android 12 SplashScreen API, and iOS Storyboards

Customize .NET MAUI 10 splash screens with Android 12 SplashScreen API, iOS LaunchScreen storyboards, Lottie animations, dark mode variants, and white-flash fixes.

MAUI 10 Splash Screen Guide (2026)

Updated: June 28, 2026

A .NET MAUI 10 splash screen is configured with the <MauiSplashScreen> build action in your .csproj, which generates an iOS LaunchScreen storyboard and an Android 12+ SplashScreen theme automatically. That single image is a lowest-common-denominator solution, though. To get animated content, dark-mode variants, brand-correct backgrounds, or anything close to parity with what native iOS and Android teams ship, you have to either override the platform output or replace it with hand-rolled Storyboard.storyboard and android:windowSplashScreen* resources. This guide walks both paths in production detail. (I've shipped MAUI apps to both stores with custom splashes, and the gotchas below cost me real time.)

  • MauiSplashScreen is a single PNG/SVG that .NET MAUI 10 fans out to iOS and Android. Fine for prototypes, painful for brand work.
  • Android 12+ enforces the SplashScreen API system-wide. The icon must fit a 240dp circle with safe-area padding, and your icon background can be a color or 9-patch.
  • iOS deprecated launch images entirely. LaunchScreen.storyboard is the only supported path, and App Store Connect rejects builds without one as of Xcode 17.
  • To animate, run the system splash for ~500 ms, then show a MAUI ContentPage with a Lottie or skeleton layout. The OS won't let you animate the real splash on iOS.
  • Most "white flash" reports stem from a mismatched window background color in styles.xml or a missing dark variant in the iOS asset catalog.
  • Splash duration is dictated by JIT/AOT startup time. See the startup performance guide for trimming and AOT.

How the MauiSplashScreen build action works

When you scaffold a new .NET MAUI 10 app, the project template drops a single line into your .csproj:

<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />

That build action is processed by the Microsoft.Maui.Resizetizer task. On iOS, it generates a MauiSplash.storyboard derived from the asset and registers it as UILaunchStoryboardName in your generated Info.plist. On Android, it produces drawable resources and wires up android:windowSplashScreenBackground and android:windowSplashScreenAnimatedIcon in Resources/values-v31/styles.xml. The same source asset is also rasterized for pre-Android-12 (API 30 and below), where it acts as the activity window background until your MainActivity is ready to draw.

The result is portable but minimal: a single static glyph centered on a flat color. Anything beyond that (bottom-of-screen wordmarks, gradient backgrounds, secondary brand assets, or motion) requires overriding the generated outputs. Good news: the override path is well-trodden once you understand what the OS actually allows on each platform.

How do I customize the splash screen on Android 12+?

Android 12 (API 31) introduced the system SplashScreen API, and Google made it mandatory. You can't opt out, even by overriding the activity theme. Every cold launch shows the system splash, period. What you control is the icon, the icon background, the window background, and an optional brand image at the bottom.

To override what MAUI generates, create Platforms/Android/Resources/values-v31/styles.xml manually:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <style name="Maui.SplashTheme" parent="Theme.SplashScreen">
    <!-- The window background shown around the icon -->
    <item name="windowSplashScreenBackground">@color/splash_background</item>

    <!-- Static icon (240dp; inner 160dp drawable area) -->
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>

    <!-- Optional: brand image fixed to the bottom of the screen -->
    <item name="android:windowSplashScreenBrandingImage">@drawable/wordmark</item>

    <!-- Optional: icon background (color or drawable) -->
    <item name="windowSplashScreenIconBackgroundColor">@color/splash_icon_bg</item>

    <!-- The theme to switch to after splash completes -->
    <item name="postSplashScreenTheme">@style/Maui.MainTheme</item>
  </style>
</resources>

The icon drawable must fit inside the inner 160dp area of the 240dp icon container. If your artwork bleeds past that, Android clips it to a circle and you get an unhappy cropped logo. The windowSplashScreenBrandingImage is the only way to get a bottom wordmark on Android 12+, and it requires API 31 or higher to render. On API 30 and below, Android falls back to android:windowBackground on your activity theme, which is what MAUI configures from the rasterized splash PNG.

Keeping the splash visible until data loads

If your app needs to fetch user state before showing UI, install the AndroidX SplashScreen compat library and call setKeepOnScreenCondition in MainActivity.OnCreate:

protected override void OnCreate(Bundle savedInstanceState)
{
    var splash = AndroidX.Core.SplashScreen.SplashScreen.InstallSplashScreen(this);
    splash.SetKeepOnScreenCondition(new KeepOnScreenCondition(() => !App.IsReady));
    base.OnCreate(savedInstanceState);
}

class KeepOnScreenCondition : Java.Lang.Object, AndroidX.Core.SplashScreen.SplashScreen.IKeepOnScreenCondition
{
    private readonly Func<bool> _shouldKeep;
    public KeepOnScreenCondition(Func<bool> shouldKeep) => _shouldKeep = shouldKeep;
    public bool ShouldKeepOnScreen() => _shouldKeep();
}

Be careful here: holding the splash longer than two seconds violates Google Play's app quality guidelines, and Pre-Launch Reports flag it. Use a skeleton screen instead if your data fetch is slow.

Customizing the iOS LaunchScreen storyboard

Apple deprecated launch images in iOS 13 and removed the launch-image asset catalog path entirely in Xcode 14. As of Xcode 17 (the version bundled with .NET 10 workloads), LaunchScreen.storyboard is the only mechanism iOS will accept, and App Store Connect rejects builds without one on first submission.

To replace what MAUI generates, create Platforms/iOS/LaunchScreen.storyboard and reference it in Info.plist:

<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>

Then either remove the <MauiSplashScreen> element from your .csproj entirely, or scope it to Android only:

<MauiSplashScreen Condition="$(TargetFramework.Contains('-android'))"
                  Include="Resources\Splash\splash.svg"
                  Color="#512BD4"
                  BaseSize="128,128" />

The storyboard can contain anything Interface Builder supports: images from your asset catalog, vector PDFs, multiple constraints, dark-mode variants. But it must be entirely static. iOS hands the launch storyboard to SpringBoard, which renders it as a snapshot image before your app process is even created. No animations, no code execution, no fonts loaded from your bundle. If you need motion, that has to happen in your first MAUI page (see the next section).

Can I animate the splash screen in .NET MAUI?

Yes, but not the OS-owned splash itself. The trick used by every native iOS/Android team, and what you need to replicate in MAUI 10, is a two-stage launch: the OS splash hands off to a transparent or color-matched MAUI ContentPage that runs the actual animation. The illusion of one continuous splash works because the background color and icon position match between the static OS splash and the MAUI page that takes over.

Here's the pattern with SkiaSharp.Extended.UI.Maui for Lottie playback:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:skia="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
             x:Class="MyApp.AnimatedSplashPage"
             BackgroundColor="#512BD4">
  <Grid>
    <skia:SKLottieView x:Name="Lottie"
                       Source="logo_intro.json"
                       RepeatCount="0"
                       HorizontalOptions="Center"
                       VerticalOptions="Center"
                       WidthRequest="180"
                       HeightRequest="180" />
  </Grid>
</ContentPage>
public partial class AnimatedSplashPage : ContentPage
{
    public AnimatedSplashPage()
    {
        InitializeComponent();
        Lottie.AnimationCompleted += async (_, _) =>
        {
            Application.Current.Windows[0].Page = new AppShell();
        };
    }
}

Set App.MainPage = new AnimatedSplashPage() in your App.xaml.cs, ship a Lottie animation that starts on the exact frame the OS splash was last showing, and you'll get a smooth animated launch with no perceptible cut. For a deeper dive on Lottie integration including JSON optimization, see the MAUI animations guide.

Dark mode and dynamic color splash screens

Both platforms support dark variants, and both punish you for forgetting them. On iOS, the asset catalog handles this natively: add a splash_logo.imageset, set "Appearances: Any, Dark", and provide both images. The storyboard automatically picks the right one based on UITraitCollection.UserInterfaceStyle.

On Android, create a values-night-v31/styles.xml alongside your light theme:

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <style name="Maui.SplashTheme" parent="Theme.SplashScreen">
    <item name="windowSplashScreenBackground">@color/splash_background_dark</item>
    <item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon_dark</item>
    <item name="postSplashScreenTheme">@style/Maui.MainTheme</item>
  </style>
</resources>

This pairs naturally with full app theming. See the dark mode and dynamic theming guide for how to make sure the splash hand-off doesn't introduce a color flash on system theme change. If your MAUI page's background color doesn't match the splash background for the current appearance, the user sees a flicker as the splash transitions to your first frame.

Why is my MAUI splash screen showing a white flash?

The white flash between the splash and your first MAUI page is the #1 splash screen support thread on the .NET MAUI GitHub repo, and it has three distinct causes. Most teams fix the wrong one.

Cause 1: Mismatched window background

The MAUI generated MainTheme sets android:windowBackground to ?attr/colorBackground, which defaults to white in the light Material theme. Override it explicitly in Platforms/Android/Resources/values/styles.xml:

<style name="Maui.MainTheme" parent="Theme.Material3.DayNight.NoActionBar">
  <item name="android:windowBackground">@color/splash_background</item>
</style>

This makes the activity window match the splash color until your MAUI surface draws its first frame.

Cause 2: iOS launch storyboard background mismatch

If your LaunchScreen.storyboard root view is white (the Interface Builder default) but your MAUI app uses a colored background, you'll see a flash even though both the launch image and the MAUI page render correctly. Open the storyboard, select the root view, and set its background to the same color asset your MAUI app uses on first render.

Cause 3: Long startup time exposing the transition

If startup is slow enough, typically >800 ms on cold launch, the system splash dismisses before your MAUI page draws, and the platform fills the gap with the activity window background. The fix is shorter startup, not splash configuration. Native AOT, trimming, and the startup tracing techniques in the performance guide reliably take cold start under 500 ms.

How long does the splash screen display in .NET MAUI?

The .NET MAUI splash screen displays for exactly as long as your app takes to render its first frame. No longer, no shorter. The OS dismisses the splash the moment your MainPage reports its first paint. You can't extend it with a Task.Delay in App.xaml.cs; that just blocks the MAUI page from drawing, and the splash stays up until the delay completes, which violates platform guidelines.

Typical durations on cold launch in .NET MAUI 10 on a mid-tier Android device:

ConfigurationCold startWarm startSplash visible
JIT, no trimming1400 ms320 ms~1400 ms
JIT + full trimming950 ms280 ms~950 ms
Native AOT (Android)520 ms180 ms~520 ms
NativeAOT + Startup Tracing380 ms140 ms~380 ms

Sub-500 ms is the threshold where users perceive the launch as instantaneous. If your splash sits longer than 800 ms on cold launch, the bottleneck isn't the splash configuration but startup work. See profiling in the dotnet/maui performance wiki.

Common splash screen pitfalls and fixes

Honestly, a few patterns keep showing up in code reviews and Discord threads:

  • Splash icon renders too small on tablets. The BaseSize on MauiSplashScreen defaults to your image's pixel dimensions. For an SVG with a 512px viewBox, set BaseSize="512,512" so the resizer scales correctly for xxxhdpi tablets.
  • Android branding image not appearing. The windowSplashScreenBrandingImage attribute requires API 31 or higher and only renders on devices running Android 12+. On 11 and below, it's silently ignored.
  • iOS storyboard images missing on first install. If you reference an asset catalog image in the storyboard, make sure the asset catalog itself ships in the iOS app bundle, not just in the MAUI shared project. Use BundleResource with the right TargetFramework condition.
  • Splash flashes a second time after deep link. Cold-launching from a deep link runs the splash; warm-launching from the recents tray does not. If you're seeing a splash on every deep link, your activity is being recreated. See the deep linking guide for the singleTask launchMode configuration that prevents this.
  • Splash doesn't update after rebuild. Android caches splash drawables aggressively. Run dotnet build -t:Clean and uninstall the app from the device. dotnet build -t:Install won't replace cached resources.

Frequently Asked Questions

Can I disable the splash screen entirely in .NET MAUI 10?

No. iOS requires a LaunchScreen.storyboard for App Store submission, and Android 12+ enforces the system SplashScreen on every cold launch. The best you can do is make the splash color-match your first MAUI page so it appears as one continuous launch.

Why does my MAUI splash icon look cropped on Android 12+?

Android 12+ enforces a 240dp icon container with a 160dp safe area. If your icon's visible content extends past that inner area, the system clips it. Resize the artwork inside the SVG viewBox so the meaningful content stays within the inner 160dp.

How do I make a different splash screen for iOS and Android in .NET MAUI?

Use conditional <MauiSplashScreen> items in your .csproj with Condition="$(TargetFramework.Contains('-ios'))" and a matching Android-only entry. Or replace the build action entirely with a custom LaunchScreen.storyboard on iOS and custom styles.xml on Android.

Does .NET MAUI 10 support animated splash screens out of the box?

No. The OS-owned splash is static on both platforms. The iOS launch storyboard runs before your app process starts, and Android's SplashScreen API only supports the system icon-zoom transition. Use a two-stage launch with a MAUI page running Lottie to fake an animated splash.

Why does my splash screen show longer on debug builds than release?

Debug builds run with the Mono interpreter and without trimming, so startup is 2-3x slower than release. The splash stays visible until your first frame draws, which isn't a splash configuration issue, it's a startup performance characteristic of debug mode. Compare cold start times in release configuration.

David O'Reilly
About the Author David O'Reilly

Native iOS/Android specialist turned MAUI advocate. Writes about the gritty platform details most cross-platform tutorials skip.