How to Create a Splash Screen With SwiftUI

Learn to build a splash screen that uses animation and SwiftUI to go beyond the typical static launch screen and keeps users interested while the app loads. By Rony Rozen.

Leave a rating/review
Download materials
Save for later
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Animating the Text

The “F ber” text has been there from the start, but it’s kind of boring because it’s not animating along with the ‘U’. To fix that, you’ll add two new modifiers to the Text. First, add two new states before body:

@State var textAlpha = 0.0
@State var textScale: CGFloat = 1

Now, it’s time to replace those placeholders with the actual animation.

Replace //TODO: Add code #1 for text here with:

withAnimation(Animation.easeIn(duration: uAnimationDuration).delay(0.5)) {
  textAlpha = 1.0

Second, replace //TODO: Add code #2 for text here with:

withAnimation(Animation.spring()) {
  self.textScale = self.uZoomFactor

Next, replace //TODO: Add code #3 for text here with:

self.textAlpha = 0

And finally, replace //TODO: Add code #4 for text here with:

self.textScale = 1

Now, replace Text with the following:

Text("F           BER")
  .offset(x: 20, y: 0)

Build and run your app:

The text view is responding to the changes in the two new state variables with animations! How cool is that? :]

Now, all that’s left is to add the background and your awesome splash screen animation will be complete. Take a deep breath and jump into the last part of the animation.

Animating the Background

You’ll start by adding the background of the ZStack. Since it’s the background, it should be the view at the back of the stack, so it has to appear first in the code. To do this, add a new Image view as the first element of SplashScreen‘s ZStack:

  .resizable(resizingMode: .tile)

This uses the Chimes asset to make tiles that fill the entire screen. Note that you’re using textAlpha and textScale as state variables, so the view will change its opacity and scale whenever these state variables change. Since they already change to animate the “F ber” text, you don’t have to do anything else to activate them.

Build and run the app and you’ll see the background animating along with the text:

You now need to add the ripple effect that fades the background when the Fuber ‘U’ shrinks into a square. You’ll do that by adding a semi-transparent circle right above the background view, below all the other views. That circle will animate its way from the middle of the Fuber ‘U’ to cover the entire screen and hide the background. Sounds easy enough, right?

Add these two new state variables which the circle’s animation needs:

@State var coverCircleScale: CGFloat = 1
@State var coverCircleAlpha = 0.0

Then add this new view in the ZStack, right after the background image view:

  .frame(width: 1, height: 1, alignment: .center)

Now, you need to change the values of these state variables at the exact right moment to initiate the animation. Add this clause to runAnimationPart2(), right below self.squareScale = 1:

withAnimation(.easeOut(duration: self.fadeAnimationDuration)) {
  self.coverCircleAlpha = 1
  self.coverCircleScale = 1000

Finally, don’t forget to initialize the circle’s size and opacity when the animation is complete and is getting ready to restart. Add this to restartAnimation(), right before re-calling handleAnimations():

self.coverCircleAlpha = 0
self.coverCircleScale = 1

Now build and run your app and — drum roll please — Ta-Da! You’ve implemented the full, complex, totally-awesome animation you set out to implement. Give yourself a pat on the back. This wasn’t trivial, but you made it all the way through.

Now sit back, relax and move on to complete a couple of finishing touches that are important to remember, especially in a real app.

Finishing Touches

The animation you’ve made is pretty cool, but the way you’ve currently implemented it, the animation will keep repeating itself long after the splash screen has faded away.

This is far from great. You need to prevent the animation from restarting after the splash screen fades since it doesn’t make sense for it to continue past that point. The user won’t see it anyway, and it uses unnecessary resources.

To stop the animation from displaying longer than it needs to, add a new static variable to SplashScreen:

static var shouldAnimate = true

In handleAnimations(), wrap restartAnimation() with an if statement, which prevents it from starting over once this new Boolean is false. It should look like this:

if SplashScreen.shouldAnimate {

Now, go back to ContentView.swift, uncomment the .onAppear closure you commented out at the beginning and set shouldAnimate to false. Then, just for fun, also change the second constant to 10 so you’ll get a chance to enjoy the beautiful splash screen animation you created. It should now look like this:

.onAppear {
    DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
      SplashScreen.shouldAnimate = false
      withAnimation() {
        self.showSplash = false

Build and run your app:

You should see your cool splash screen display for 10 seconds, followed by the app’s main map view. And the best part about it is that once the splash screen disappears, it no longer animates in the background, so your users are free to experience the app in all its glory without any background animations slowing them down. Sweet!

Where to Go From Here?

You can download the final Fuber project by using the Download Materials button at the top or bottom of this tutorial.

If you’d like to learn more about animations, check out iOS Animations by Tutorials.

Have an animation question? Want to post an amusing photo you used as a tiled background? Feel free to join the forum discussion below!