Android Splash Screen Animated Icon: Specs, XML and Handoff
By the Charmotion team · Updated

An animated Android splash icon must be an AnimatedVectorDrawable on a 432 dp canvas, with the visible part inside the inner 288 dp. Google recommends keeping the animation at or under 1,000 ms on phones, with any delayed start no longer than 166 ms. It animates on Android 12 and later; on older versions the androidx compat library shows a still icon.
Key takeaways
- Only an AnimatedVectorDrawable can animate in the system splash; Lottie, GIF and PNG sequences cannot.
- Draw on a 432 dp canvas and keep the visible content inside the inner 288 dp (two thirds).
- On Android 12 (targeting API 31 or 32) set
windowSplashScreenAnimationDuration; Android 13 reads the length from the AVD. - Set
android:windowSplashScreenBehaviortoicon_preferredon Android 13+ so the icon always shows. - Use
setOnExitAnimationListenerto fade the splash out and hand off to a full intro on your first screen.
Already have a character or logo? See your character in real app screens: splash, onboarding, loading and empty-state screens. It's free, runs in your browser and uploads nothing.
What are the Android splash screen icon specs?
These come from Google's splash screen documentation and the androidx SplashScreen reference (Android Developers):
| Item | Spec |
|---|---|
| Animated icon format | AnimatedVectorDrawable (AVD) XML |
| Animated icon canvas | 432 dp (four times an adaptive icon); the inner two thirds, 288 dp, is visible |
| Static icon with icon background | 240×240 dp, content within a 160 dp circle |
| Static icon without icon background | 288×288 dp, content within a 192 dp circle |
| Branding image (optional) | 200×80 dp |
| Background | A single color, windowSplashScreenBackground |
| Animation length | Recommended not to exceed 1,000 ms on phones |
| Delayed start | No longer than 166 ms |
| Slow startup | If startup takes longer than 1,000 ms, consider a looping animation |
| Animated on | Android 12 (API 31) and later |
The compat library androidx.core:core-splashscreen brings the same splash to devices from API 23, but its reference is explicit: before API 31 the platform behavior is replicated "with the exception of the Animated Vector Drawable support" (androidx reference). Put the animated drawable in res/drawable-v31 and a still version in res/drawable.
How do you set up an animated splash icon in XML?
You need three pieces: the AVD, a starting theme, and one call in your launcher activity. A minimal AVD that pops a shape in with an overshoot (replace the path with your icon's vector paths, kept inside the central 288 dp):
<!-- res/drawable-v31/splash_icon.xml -->
<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:width="432dp" android:height="432dp"
android:viewportWidth="432" android:viewportHeight="432">
<group android:name="icon" android:pivotX="216" android:pivotY="216">
<path android:fillColor="#FFFFFF"
android:pathData="M216,136a80,80 0 1,1 0,160a80,80 0 1,1 0,-160z" />
</group>
</vector>
</aapt:attr>
<target android:name="icon">
<aapt:attr name="android:animation">
<set>
<objectAnimator android:propertyName="scaleX" android:duration="600"
android:valueFrom="0.6" android:valueTo="1"
android:interpolator="@android:interpolator/overshoot" />
<objectAnimator android:propertyName="scaleY" android:duration="600"
android:valueFrom="0.6" android:valueTo="1"
android:interpolator="@android:interpolator/overshoot" />
</set>
</aapt:attr>
</target>
</animated-vector>
The starting theme, using the compat library:
<!-- res/values/themes.xml -->
<style name="Theme.App.Starting" parent="Theme.SplashScreen">
<item name="windowSplashScreenBackground">@color/brand_background</item>
<item name="windowSplashScreenAnimatedIcon">@drawable/splash_icon</item>
<item name="windowSplashScreenAnimationDuration">600</item>
<item name="postSplashScreenTheme">@style/Theme.App</item>
</style>
<!-- res/values-v33/themes.xml: same style, plus -->
<item name="android:windowSplashScreenBehavior">icon_preferred</item>
Set android:theme="@style/Theme.App.Starting" on the application or launcher activity in the manifest, then call installSplashScreen() before super.onCreate(), as Google's migration guide shows (Android Developers).
icon_preferred exists because, by default on Android 13 and later, the system may show the splash without the icon depending on how the activity was launched. Google says to set it if you never want an empty splash and always want the animated icon displayed.
How do you control how long the splash icon animates?
Two separate things are easy to mix up: how long the icon animates, and how long the splash stays on screen.
- Android 12 (apps targeting API 31 or 32): set
windowSplashScreenAnimationDurationso the animation plays while the starting window shows. Google says this isn't required on Android 13, because the duration is inferred directly from the AnimatedVectorDrawable. - The attribute never extends the splash. Both Google's guide and the androidx reference say it has no effect on how long the splash is displayed; in the compat library it only feeds
SplashScreenViewProvider.iconAnimationDurationMillis. - To keep the splash up while you load, use
splashScreen.setKeepOnScreenCondition { !viewModel.isReady }. The condition is checked before each draw, so keep it cheap.
Stay within the 1,000 ms recommendation for the icon animation itself. If your app is often slower than that to start, design the AVD so its end state can loop or hold calmly, rather than stretching a single motion. And if the app is ready in 300 ms, let the splash go: nobody opened your app to watch it.
Why can't you put Lottie, a GIF or a PNG sequence in the splash?
Because the system draws the splash from your theme as a starting window, before your activity has drawn anything, and the only animated drawable it supports there is the AnimatedVectorDrawable XML named in windowSplashScreenAnimatedIcon. A Lottie file needs the Lottie library running inside your process, a GIF needs a decoder and a view, and a PNG sequence is just a list of bitmaps. None of them can be referenced from a theme attribute.
That also tells you what an AVD can and cannot do well. It animates vector paths, groups and their properties (rotation, scale, translation, path morphing, alpha). A flat, geometric logo translates cleanly. A detailed character, a gradient-heavy or 3D icon, or anything raster will not, and forcing it usually means simplifying the artwork.
The practical split: keep the system splash simple (a still icon, or a short AVD pop-in), and play the rich animation in your app, where Lottie, Rive and video all work. Compare the options in Lottie vs Rive vs video for a splash screen.
How do you hand off from the splash to a full intro?
Register an exit listener. Once it is set, the splash is no longer removed automatically, and you call remove() when your own exit animation ends (androidx reference):
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val splash = installSplashScreen()
super.onCreate(savedInstanceState)
splash.setOnExitAnimationListener { provider ->
provider.view.animate()
.alpha(0f)
.setDuration(200L)
.withEndAction { provider.remove() }
.start()
}
setContentView(R.layout.activity_intro) // first screen plays the intro
}
}
The first screen sits on the same background color with the icon at the same size and center, so the fade reveals what looks like the same icon, which then starts its full intro. With a Rive file, the legacy view can play a launch state machine straight from XML:
<app.rive.runtime.kotlin.RiveAnimationView
android:id="@+id/intro"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_gravity="center"
app:riveResource="@raw/launch"
app:riveStateMachine="LaunchStateMachine" />
Then wait for the intro's length before moving on. A Charmotion LaunchStateMachine plays a 2.6-second intro once, ends on the resting icon and fires no end event, so schedule the next step with a timer (for example intro.postDelayed({ showHome() }, 2600)) instead of waiting for a callback. Rive's Android docs cover setup with Rive.init(context) (Rive).
Charmotion does not export AnimatedVectorDrawable. Its files cover the in-app half of this handoff (.riv, transparent WebM and HEVC MOV, MP4); the AVD in the system splash is something you draw in vector form or keep as a still icon.
What goes wrong most often with Android splash icons?
- Cropped artwork. Content outside the inner two-thirds circle is masked. Design inside 288 dp of the 432 dp canvas for the animated icon, or 192 dp of 288 dp for a static one.
- An adaptive icon reused as the splash icon on old versions. The androidx reference warns that before API 31 an adaptive icon in
windowSplashScreenAnimatedIconis cropped and scaled; it suggests using the foreground layer and the icon background color instead. - Expecting animation below Android 12. The compat library shows the icon still. Ship the animated drawable in
drawable-v31only. installSplashScreen()aftersuper.onCreate()or a missingpostSplashScreenTheme, which leaves the activity on the splash theme.- An animation that outlasts startup. Past roughly a second, users notice they are waiting for a logo. Keep the AVD short and let the in-app intro carry the personality.
For the cross-platform picture, including iOS, see app launch and splash screen animation.
How to add an animated icon to the Android splash screen
- Draw the AVD. Create an AnimatedVectorDrawable on a 432 dp canvas with visible content inside the central 288 dp, animating for no more than about 1,000 ms.
- Split by API level. Put the animated drawable in
res/drawable-v31and a still version inres/drawablefor older devices. - Create the starting theme. Extend
Theme.SplashScreen, setwindowSplashScreenBackground,windowSplashScreenAnimatedIcon,windowSplashScreenAnimationDurationandpostSplashScreenTheme, and addicon_preferredinvalues-v33. - Install it. Apply the theme in the manifest and call
installSplashScreen()beforesuper.onCreate(). - Hand off. Use
setOnExitAnimationListenerto fade the splash out, then play the full intro on a first screen with the same background, waiting for its length before showing the app.
Frequently asked questions
Can I use a Lottie file as the Android splash icon?
No. The splash icon comes from a theme attribute, and the animated form must be an AnimatedVectorDrawable. Lottie needs its library running in your app, so play the Lottie animation on your first screen after the splash exits, on the same background color.
Does windowSplashScreenAnimationDuration keep the splash on screen longer?
No. Google's documentation says it has no effect on how long the splash screen is shown. It tells Android 12 how long to run the icon animation. To hold the splash while your app loads, use setKeepOnScreenCondition.
Can the Android splash screen show a branding image?
Yes. Besides the centered icon, the splash screen can show an optional branding image at the bottom, sized 200×80 dp according to Google's documentation. Keep it simple, since it sits on the same single background color and appears on every cold start.
What does icon_preferred do?
On Android 13 and later, android:windowSplashScreenBehavior set to icon_preferred tells the system to always show your icon on the splash, instead of sometimes showing an empty splash depending on how the activity was launched.
Quick answers from this guide
Sources
- Splash screens, Android Developers
- Migrate your splash screen implementation to Android 12 and later, Android Developers
- SplashScreen (androidx.core:core-splashscreen), Android Developers
- AnimatedVectorDrawable, Android Developers
- Adaptive icons, Android Developers
- Android runtime, Rive