Animated Splash Screen in .NET MAUI Android
Tags: dotnet, android, dotnetmaui, mauiuijuly
Published: 2024-07-03 16:24:13

> This article is part of the [#MAUIUIJuly](https://goforgoldman.com/posts/mauiuijuly-24/) initiative by [Matt Goldman](https://twitter.com/mattgoldman). You'll find other helpful articles and tutorials published daily by community members and experts there, so make sure to check it out every day.

Beginning with **Android 12**, the [Splash Screen API](https://developer.android.com/develop/ui/views/launch/splash-screen) allows you to define an animated splash screen that plays when the app starts (without having to set up a custom Activity with a gif or an animation, as some people would not consider it a *true splash screen*). This API also allows you to:

* customize the icon background color
* customize the window background color
* set up a transition to the app after the splash screen plays

Before I explain how to do it in a .NET MAUI app, let's be clear about some important things:

- An animated splash screen in Android is defined as an [Animated Vector Drawable](https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable).

- Currently, Launch Screens on iOS can't be animated unless you [apply some tricks](https://createwithflow.com/tutorials/launchAnimationStepByStep/) (in general, you can do the same in a .NET MAUI app, simply set the `MainPage` in `App.xaml.cs` to any `ContentPage` which starts immediately after the static Splash Screen plays and that contains some sort of animation, such as a .gif, a [Lottie animation](https://www.youtube.com/watch?v=o5X5yXdWpuc) or of course, [Animations](https://learn.microsoft.com/en-us/dotnet/maui/user-interface/animation/basic?view=net-maui-8.0)). Then, after the animation ends, navigate to your _true Home Page_. However, some people might argue that that's not really a Splash Screen, although it does the job of playing an animation before the user is finally able to interact with the application :)

- Disclaimer: this is not really a new topic. Several blog posts on Internet already talk about the Splash Screen Android API in a .NET MAUI app to customize the window and icon background color, for example. However, I only found [one](https://blog.noser.com/android-splash-screen-api-and-dotnet-maui/) -in German language- which implements the animated splash screen. By the way, [here](https://trailheadtechnology.com/android-splash-screen-logos-and-animations-with-xamarin/) is another blog post that explains how to do the same for our old good pal Xamarin.

Anyways, let's code!

## Step 1. Add a NuGet package 

Add the `Xamarin.AndroidX.Core.SplashScreen` NuGet package to your .NET MAUI project.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o4fj7cdm1td8dll7pu8g.png)

## Step 2. Add an AVD as an AndroidResource

Add the Animated Vector Drawable where you define your animation. You can use tools such as [ShapeShifter](https://shapeshifter.design/) to create them from SVG files. There is also an interesting [CLI tool](https://github.com/garawaa/lottie-to-avd) that converts Lottie Json Animations to Android Animated Vector Drawable XML 

- You might need to create a `drawable` folder under `Platforms/Android/Resources`.
- Set the `Build Action` of the file to `AndroidResource`.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/44g0xh6ordet45x3jxyf.png)

Sample Animated Vector Drawable:

```
<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
	<aapt:attr name="android:drawable">
		<vector
            android:name="vector"
            android:width="32dp"
            android:height="32dp"
            android:viewportWidth="32"
            android:viewportHeight="32">
			<group android:name="group">
				<path
                    android:name="path_end"
                    android:pathData="M 15.12 15.53 L 25 5.66 C 25.191 5.496 25.437 5.411 25.689 5.42 C 25.941 5.43 26.18 5.534 26.358 5.712 C 26.536 5.89 26.64 6.129 26.65 6.381 C 26.659 6.633 26.574 6.879 26.41 7.07 L 17.35 16.13 L 26.15 24.93 C 26.336 25.117 26.441 25.371 26.441 25.635 C 26.441 25.899 26.336 26.153 26.15 26.34 C 26.026 26.465 25.871 26.555 25.7 26.601 C 25.53 26.647 25.35 26.647 25.18 26.601 C 25.009 26.555 24.854 26.465 24.73 26.34 L 15.12 16.73 C 14.961 16.571 14.872 16.355 14.872 16.13 C 14.872 15.905 14.961 15.689 15.12 15.53 Z"
                    android:fillColor="#00446a"
                    android:fillAlpha="0"
                    android:strokeWidth="1"/>
				<path
                    android:name="path_start"
                    android:pathData="M 5.54 15.53 L 15.42 5.66 C 15.564 5.492 15.76 5.376 15.978 5.331 C 16.195 5.286 16.421 5.315 16.62 5.413 C 16.819 5.51 16.98 5.671 17.077 5.87 C 17.175 6.069 17.204 6.295 17.159 6.512 C 17.114 6.73 16.998 6.926 16.83 7.07 L 7.77 16.13 L 16.57 24.93 C 16.756 25.117 16.861 25.371 16.861 25.635 C 16.861 25.899 16.756 26.153 16.57 26.34 C 16.383 26.526 16.129 26.631 15.865 26.631 C 15.601 26.631 15.347 26.526 15.16 26.34 L 5.54 16.73 C 5.381 16.571 5.292 16.355 5.292 16.13 C 5.292 15.905 5.381 15.689 5.54 15.53 Z"
                    android:fillColor="#00446a"
                    android:fillAlpha="0"
                    android:strokeWidth="1"/>
			</group>
		</vector>
	</aapt:attr>
	<target android:name="path_start">
		<aapt:attr name="android:animation">
			<set>
				<objectAnimator
					android:propertyName="fillAlpha"
					android:startOffset="500"
					android:duration="500"
					android:valueFrom="0"
					android:valueTo="1"
					android:valueType="floatType"
					android:interpolator="@android:anim/linear_interpolator"/>
				<objectAnimator
                    android:propertyName="fillColor"
					android:startOffset="1000"
                    android:duration="500"
                    android:valueFrom="#00446a"
                    android:valueTo="#ff2266"
                    android:valueType="colorType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
				<objectAnimator
					android:propertyName="fillAlpha"
					android:startOffset="2000"
					android:duration="500"
					android:valueFrom="1"
					android:valueTo="0.5"
					android:valueType="floatType"
					android:interpolator="@android:anim/linear_interpolator"/>
				<objectAnimator
					android:propertyName="fillAlpha"
					android:startOffset="2500"
					android:duration="500"
					android:valueFrom="0.5"
					android:valueTo="1"
					android:valueType="floatType"
					android:interpolator="@android:anim/linear_interpolator"/>
			</set>
		</aapt:attr>
	</target>
	<target android:name="path_end">
		<aapt:attr name="android:animation">
			<set>
				<objectAnimator
					android:propertyName="fillAlpha"
					android:startOffset="300"
					android:duration="800"
					android:valueFrom="0"
					android:valueTo="1"
					android:valueType="floatType"
					android:interpolator="@android:anim/linear_interpolator"/>
			    <objectAnimator
                    android:propertyName="fillAlpha"
                    android:startOffset="1100"
                    android:duration="800"
                    android:valueFrom="1"
                    android:valueTo="0.5"
                    android:valueType="floatType"
                    android:interpolator="@android:anim/linear_interpolator"/>
				<objectAnimator
                    android:propertyName="fillAlpha"
                    android:startOffset="1900"
                    android:duration="600"
                    android:valueFrom="0.5"
                    android:valueTo="1"
                    android:valueType="floatType"
                    android:interpolator="@android:anim/linear_interpolator"/>
			</set>
		</aapt:attr>
	</target>
</animated-vector>
```

## Step 3. Define a Theme

Next up, add a `themes.xml` file under `Platforms/Android/Resources/values`. Set its `Build Action` to `AndroidResource` as well.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xxv2xaccuz6nkpnklajy.png)


In this file you configure a `style`:

- You **must** set a name for your theme (style) because it will be referenced later in `MainActivity.cs`.
- The theme **must** inherit from `Theme.SplashScreen` (use the `parent` property for that).
- You **must** set the element in the animated splash screen using the `windowSplashScreenAnimatedIcon` attribute in an `item` element.
- You must set the `windowSplashScreenAnimationDuration` value **only if your app targets Android 12**. Otherwise, the value is optional and is  obtained from the Animated Vector Drawable itself.
- The `windowSplashScreenBackground` that defines the background color for the starting window is **optional**.
- According to [this reference](https://developer.android.com/develop/ui/views/launch/splash-screen/migrate), you **must** also set the `postSplashScreenTheme` property to the theme that the Activity will use after the Splash Screen dissapears.

Sample code for `themes.xml`:

```
<resources>
	<style name="Theme.Animated" parent="Theme.SplashScreen">
		<item name="windowSplashScreenBackground">@android:color/white</item>
		<item name="windowSplashScreenAnimatedIcon">@drawable/cloud</item>
		<item name="windowSplashScreenAnimationDuration">1300</item>
		<item name="postSplashScreenTheme">@style/Maui.MainTheme.NoActionBar</item>
	</style>
</resources>
```

## Step 4. Call InstallSplashScreen in MainActivity before calling base.onCreate().

- In `MainActivity.cs`, override its `onCreate` method and invoke the `InstallSplashScreen` static function before `base.onCreate()`. 

- The class `AndroidX.Core.SplashScreen.SplashScreen` is required and it can be imported with the `static` modifier. 

- And don't forget to set the value for `Theme` in the `Activity` attribute. Simply set it to the name that you previously defined in your style (in `themes.xml`):

Code for `MainActivity.cs`:

```
using Android.App;
using Android.Content.PM;
using Android.OS;

using static AndroidX.Core.SplashScreen.SplashScreen;

namespace AnimatedSplashScreenApp
{
    [Activity(Theme = "@style/Theme.Animated", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
    public class MainActivity : MauiAppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            var splash = InstallSplashScreen(this);
            base.OnCreate(savedInstanceState);
        }
    }
}
```

## Step 5. (Clean, Re)Build & Test your App

Now you can build and test your app. This is the outcome:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b2lh2ycvtmhzslwvj9uq.gif)

In case you edit the animation and can't see the latest version of it, simply Clean and Rebuild the project.

As you can see, it is very easy to add an animated splash screen in Android using .NET MAUI. Perhaps the hardest part is to play with the svg and create an animation from it. You can get some inspiration from these [animated vector drawables](https://github.com/alexjlockwood/adp-delightful-details) or learn more about the Shape Shifter tool with a [tutorial](https://medium.com/@ecspike/creating-animatedvectordrawables-with-shape-shifter-543d099285b9).

By the way, you can do even more things. As explained [here](https://blog.noser.com/android-splash-screen-api-and-dotnet-maui/) -in German language-: 

- There can be situations in which you want to extend the animation display time because you would like to do some work in the background, such as loading app settings or data before the first view is displayed. To do this, you can register a listener with the `ViewTreeObserver` and define a `OnPreDraw` function from the `IOnPreDrawListener` interface on `MainActivity`. 

- By implementing the `IOnExitAnimationListener` interface, you can set the exit animation, such as a slide-up that looks pretty neat.

- You can also add a branding image in your Splash Screen by defining it in the style (`themes.xml`). Use the [`windowSplashScreenBrandingImage`](https://developer.android.com/develop/ui/views/launch/splash-screen) property for that.

The source code of this blog post can be found [here](https://github.com/icebeam7/AnimatedSplashScreenApp).

I hope that this post was interesting and useful for you. Thanks for your time, and enjoy the rest of the [#MAUIUIJuly](https://goforgoldman.com/posts/mauiuijuly-24/) publications!

## Other references

1. [Let's customize the Splash Screen of a MAUI app](https://blog.ewers-peters.de/lets-customize-the-splash-screen-of-a-maui-app)
2. [Sketch + Animated Vector Drawable = ❤️](https://proandroiddev.com/sketch-animated-vector-drawable-%EF%B8%8F-41fb63465b61)
3. [An Introduction to Icon Animation Techniques](https://www.androiddesignpatterns.com/2016/11/introduction-to-icon-animation-techniques.html)