Animated Splash Screen in Android Studio with the SplashScreen API
Add a modern animated splash screen using the official SplashScreen API, the way Android 12 and later expect it. Your app icon animates in, then the app opens without a separate splash activity.
Then press Sync Now. It brings the Android 12 splash to older versions too.
3. Draw the icon
Add your logo as a vector drawable. Keep the artwork inside the middle 72dp of the 108dp canvas, because the splash crops it into a circle. Put the shapes you want to move inside a named <group>.
4. Animate it
Create a res/animator folder and an animator that changes the group's scaleX, scaleY and rotation. Then an animated-vector drawable connects the group's name to that animator.
5. Create the Starting theme
In themes.xml, add a theme whose parent is Theme.SplashScreen, and set:
windowSplashScreenBackground: the background colour
windowSplashScreenAnimatedIcon: your animated drawable
windowSplashScreenAnimationDuration: how long the animation runs
postSplashScreenTheme: your normal app theme, used after the splash
Give the application this theme in the manifest.
6. Install the splash
In MainActivity.onCreate, call SplashScreen.installSplashScreen(this)beforesuper.onCreate().
7. Keep it up while loading
setKeepOnScreenCondition keeps the splash visible while it returns true. Set your ready flag when loading finishes. The sample waits 1.5 seconds to stand in for real work.
8. Animate it away
setOnExitAnimationListener gives you the splash view and its icon. Shrink and fade them, and call remove() when the animation ends.
9. Run it
Close the app completely and open it again from the launcher: the icon pops in, holds while "loading", then shrinks away. Android Studio's Run button sometimes skips the splash, so test from the launcher.
If something goes wrong
No animation: the animated icon plays on Android 12 and later. Older versions show the static icon.
Crash on launch:installSplashScreen must come before super.onCreate(), and the manifest must use the Starting theme.
The app looks wrong after the splash: check postSplashScreenTheme points to your normal theme.
Files affected
Check what to add and what to replace before copying code.
Installs the splash, keeps it up while loading, and animates it away.
MainActivity.java
packagecom.example.animatedsplashscreen;importandroid.animation.Animator;importandroid.animation.AnimatorListenerAdapter;importandroid.animation.AnimatorSet;importandroid.animation.ObjectAnimator;importandroid.os.Bundle;importandroid.os.Handler;importandroid.os.Looper;importandroid.view.View;importandroid.view.animation.AnticipateInterpolator;importandroidx.activity.EdgeToEdge;importandroidx.appcompat.app.AppCompatActivity;importandroidx.core.graphics.Insets;importandroidx.core.splashscreen.SplashScreen;importandroidx.core.view.ViewCompat;importandroidx.core.view.WindowInsetsCompat;/**
* Uses the official SplashScreen API, so there is no separate splash activity.
* 1. installSplashScreen() shows the animated icon set in the theme.
* 2. setKeepOnScreenCondition() keeps it up until the app is ready.
* 3. setOnExitAnimationListener() animates it away.
*/publicclassMainActivityextendsAppCompatActivity{privatevolatileboolean ready =false;@OverrideprotectedvoidonCreate(Bundle savedInstanceState){// Must be called before super.onCreate().SplashScreen splashScreen =SplashScreen.installSplashScreen(this);super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main),(v, insets)->{Insets bars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(bars.left, bars.top, bars.right, bars.bottom);return insets;});// Keep the splash on screen while the app "loads". Replace the delay with your real loading work.
splashScreen.setKeepOnScreenCondition(()->!ready);newHandler(Looper.getMainLooper()).postDelayed(()-> ready =true,1500);// When the splash leaves, shrink the icon and fade the splash, then remove it.
splashScreen.setOnExitAnimationListener(provider ->{View icon = provider.getIconView();AnimatorSet exit =newAnimatorSet();
exit.playTogether(ObjectAnimator.ofFloat(icon,View.SCALE_X,1f,0.4f),ObjectAnimator.ofFloat(icon,View.SCALE_Y,1f,0.4f),ObjectAnimator.ofFloat(provider.getView(),View.ALPHA,1f,0f));
exit.setInterpolator(newAnticipateInterpolator());
exit.setDuration(400);
exit.addListener(newAnimatorListenerAdapter(){@OverridepublicvoidonAnimationEnd(Animator animation){
provider.remove();}});
exit.start();});}}