iOS Animation Tutorial: Getting Started

In this tutorial, you’ll learn to perform UIView Animations in your code to draw the user’s attention to important elements, making your app more fun and polished. By Felipe Laso-Marsetti.

Leave a rating/review
Download materials
Save for later
Update note: Felipe Laso-Marsetti updated this tutorial for Swift 5.1, Xcode 11 and iOS 13. Marin Todorov wrote the original.

Animation is a critical part of your iOS user interfaces, giving apps the ability to draw user attention to particular areas. Using the right animation will not only improve user experience, but can also add a ton of fun and polish to your app. In a world where apps are fighting for users, using the right animations help make your app stand out from others.

In this tutorial, you’ll learn how to use UIView animation to do the following:

  • Set the stage for a cool animation.
  • Create move and fade animations.
  • Adjust the animation easing.
  • Reverse and repeat animations.

There’s a fair bit of material to get through, but it will be a lot of fun. Are you up for the challenge?

Getting Started

Use the Download Materials button at the top or bottom of this tutorial to download the starter project.

Build and run your project in Xcode. You’ll see the login screen of a fictional airline app:

First run of the starter project

Open the Main storyboard and check out the existing scene. It shows a login form with a title, two text fields and a big friendly button at the bottom. There’s also a nice background picture and four clouds.

The clouds are connected to outlet variables in the code, named cloud1 through cloud4. There are also outlets for constraints that you’ll use to animate everything.

Now, open ViewController.swift and have a look inside. At the top of the file, you’ll see all the connected outlets and class variables. Further down, there’s a method call in viewDidLoad() which initializes some of the UI.

Enough with the introductions, you’re ready to try out some code!

On Your Mark, Get Set…

Your first task is to animate the form elements onto the screen when the user opens the app. Right now, the form is visible when the app starts. You need to move it off of the screen just before your view controller appears.

In viewWillAppear(_:), replace // TODO 1 with the following:

headerLabelCenterConstraint.constant -= view.bounds.width
usernameTextFieldCenterConstraint.constant -= view.bounds.width
passwordTextFieldCenterConstraint.constant -= view.bounds.width

This changes the constants of the center constraints to place each of the form elements outside the visible bounds of the screen, like so:

Off-screen Elements

Since the code above executes before the view controller appears, those text fields will look like they were never there in the first place.

Build and run your project to make sure your fields truly appear offscreen, as you planned:

Login Screen With No Items

Perfect! Now, you’ll animate those form elements back to their original locations via a spritely animation.

Go, Animation!

Replace // TODO 2 at the end of viewDidAppear(_:) with the following code:

headerLabelCenterConstraint.constant = 0
// TODO 3    

UIView.animate(withDuration: 0.5) { [weak self] in

To animate the title into view, you call the UIView class method, animate(withDuration:animations:). The animation starts immediately and animates over half a second. You set the duration via the first method parameter in the code.

Instead of animating the label by directly changing its position, you’ll update it in two steps: First, you change the constant for its center constraint to be outside of the animation block. Next, you call layoutIfNeeded() on your controller’s view within the animation block.

By calling this method, you force the view to update its layout immediately. The Auto Layout engine then updates the position of your views as needed for them to comply with your constraint changes.

Build and run your project. You should see the title slide neatly into place, like so:

Animate The Title Label In

That sets the stage for you to animate the rest of the form elements into your view.

Since animate(withDuration:animations:) is a class method, you aren’t limited to animating just one specific view; you can animate as many views as you want.

Replace // TODO 3 with the following line:

usernameTextFieldCenterConstraint.constant = 0

Again, you’re just setting the center constraint constant back to zero so the text field animates in and gets centered from left to right.

Build and run your project again, and watch as the username field slides into place:

Animate The Username Field In

Seeing both views animate together is cool, but you probably noticed that something’s off. Animating the two views over the same distance and with the same duration looks a bit stiff. Only kill-bots move with such absolute synchronization!

Wouldn’t it be cool if each of the elements moved independently of the others, possibly with a little bit of delay between the animations?

One After Another

First, remove the line you just added that animates the username text field:

usernameTextFieldCenterConstraint.constant = 0

Then add the following code to the bottom of viewDidAppear(_:):

usernameTextFieldCenterConstraint.constant = 0
UIView.animate(withDuration: 0.5,
               delay: 0.3,
               options: [],
               animations: { [weak self] in
  }, completion: nil)

This class method looks familiar, but it has a few more parameters that let you customize your animation:

  • withDuration: Sets the duration of the animation.
  • delay: Contains the number of seconds UIKit will wait before it starts the animation.
  • options: Lets you customize several aspects about your animation. You’ll learn more about this parameter later on. For now, you’ll pass an empty array, [], to indicate “no special options.”
  • animations: The closure expression to apply your animations.
  • completion: A code closure that executes when the animation completes. This parameter comes in handy when you want to perform some final cleanup tasks or to chain animations one after the other.

In the code you added above, you set delay to 0.3 to make the username animation start just a hair later than the title animation.

Build and run your project. How does the combined animation look now?

Animate The Username Field With Delay

That looks much better. Now, all you need to do is animate in the password field.

Add the following code to the bottom of viewDidAppear(_:):

passwordTextFieldCenterConstraint.constant = 0
UIView.animate(withDuration: 0.5,
               delay: 0.4,
               options: [],
               animations: { [weak self] in
  }, completion: nil)

Here, you’ve mimicked the animation of the username field, but with a slightly longer delay.

Build and run your project again to see the complete animation sequence:

Animate All The Fields In

That’s all you need to do to animate views across the screen with a UIKit animation!

But you’re just getting started. You’ll learn more awesome animation techniques in the remainder of this tutorial!

Animatable Properties

Now that you’ve seen how easy animations can be, you probably want to learn how else you can animate your views.

This section gives you an overview of the animatable properties of a UIView, then guides you through exploring these animations in your project.

You can’t animate all view properties, but you can build all view animations, from the simplest to the most complex, by animating the subset of view properties that can animate. You’ll see how in the next section.

Position and Size

Position And Size Properties

You can animate a view’s position and frame in order to make it grow, shrink or move around, as you did in the previous section. Here are the properties you can use to modify a view’s position and size:

  • bounds: Reposition the view’s content within the view’s frame.
  • frame: Move and/or scale the view.
  • center: Move the view to a new location onscreen.

Don’t forget that in Swift, several UIKit properties, such as size and center, are mutable. This means you can move a view vertically by changing center.y or you can shrink a view by decreasing frame.size.width.

Another thing worth mentioning is that, in the code you’ve used in this tutorial, you animate the position by modifying the constraints of your elements as opposed to the center property. However, either way works.

When using Auto Layout, you may find using constraints to animate the position is less confusing. This is especially true when you’re debugging animation issues when there’s a constraint in place in addition to a modified frame.

Now that you’ve animated the position of your UI elements, it’s time to create some size animations for the clouds. Add the following code just before setUpUI():

private func animateClouds() {
    let options: UIView.AnimationOptions = [.curveEaseInOut,
    UIView.animate(withDuration: 2.9,
                   delay: 0,
                   options: options,
                   animations: { [weak self] in
                    self?.cloud1ImageView.frame.size.height *= 1.18
                    self?.cloud1ImageView.frame.size.width *= 1.18
    }, completion: nil)
    UIView.animate(withDuration: 3.0,
                   delay: 0.2,
                   options: options,
                   animations: { [weak self] in
                    self?.cloud2ImageView.frame.size.height *= 1.28
                    self?.cloud2ImageView.frame.size.width *= 1.28
    }, completion: nil)
    UIView.animate(withDuration: 2.4,
                   delay: 0.1,
                   options: options,
                   animations: { [weak self] in
                    self?.cloud3ImageView.frame.size.height *= 1.15
                    self?.cloud3ImageView.frame.size.width *= 1.15
    }, completion: nil)
    UIView.animate(withDuration: 3.2,
                   delay: 0.5,
                   options: options,
                   animations: { [weak self] in
                    self?.cloud4ImageView.frame.size.height *= 1.23
                    self?.cloud4ImageView.frame.size.width *= 1.23
    }, completion: nil)

While the method may look a bit large, it’s pretty simple. First, it creates a constant set of animation options to use for your four cloud image views, then it adds one animation block per cloud.

You set different delays and durations for each cloud, and you modify the width and height of each cloud’s image view within the animation block.

Since these properties are animatable, and since you’re using the .repeat and .autoreverse animation options, your clouds now have some very nice effects: changing size and acting all puffy.

But you won’t see those effects quite yet. To get the clouds to animate, simply add the following line at the end of viewDidAppear(_:):


So far, you’ve made your login form and your clouds look pretty good. But how about changing up the appearance of the login button?


Appearance Properties

You can change the appearance of the view’s content by either tinting its background or making the view fully- or semi-transparent.

  • backgroundColor: Change this view property to have UIKit gradually change the background color over time.
  • alpha: Change this property to create fade-in and fade-out effects.

How about adding some color animations? Your next step is to animate the background color of the login button. To do so, add the following code at the end of viewDidAppear(_:):

UIView.animate(withDuration: 1,
                   delay: 1.2,
                   options: .curveEaseInOut,
                   animations: { [weak self] in
                    self?.loginButton.backgroundColor = .systemYellow
      }, completion: nil)

Build and run. After your label and text fields animate in, the login button’s background changes to a cool, tropical-looking yellow.

Login Button Color


Transformation Properties

Transforms modify views in much the same way as above, since they also adjust the views’ size and position.

  • transform: Modify this property within an animation block to animate the rotation, scale and/or position of a view.

These are affine transformations under the hood, which are much more powerful and allow you to describe the scale factor or rotation angle rather than providing a specific value for bounds or center point.

These look like pretty basic building blocks, but you’ll be surprised at the complex animation effects you can make with them!

Animation Options

Looking at your animation code, you’ve always passed [] to the options parameter (except for your clouds). options lets you customize how UIKit creates your animation. So far, you’ve only adjusted the duration and delay of your animations, but you can use options for more control over your animation parameters.

Below is a list of options declared in UIViewAnimationOptions. You can combine these options in different ways to create cool animations.

You’ll first take a look at the following two animation options:

  • .repeat: Include this option to make your animation loop forever.
  • .autoreverse: Include this option only in conjunction with .repeat. It repeatedly plays your animation forward, then in reverse.

Modify the code that animates the password field viewDidAppear(_:) to use the .repeat option as follows:

UIView.animate(withDuration: 0.5,
               delay: 0.4,
               options: .repeat,
               animations: { [weak self] in
  }, completion: nil)

Build and run to see the effect of your change:

Repeat Animation Option

The form title and username field fly in and settle down in the center of the screen, but the password field keeps animating forever from its position offscreen.

Modify the same code you changed above to use both .repeat and .autoreverse in the options parameter as follows:

UIView.animate(withDuration: 0.5,
               delay: 0.4,
               options: [.repeat, .autoreverse],
               animations: { [weak self] in
  }, completion: nil)

Note that if you want to enable more than one option, you need to use the set syntax, listing each option separated by a comma, then enclose the list in square brackets.

Note: If you only need a single option, Swift allows you to omit the square brackets. However, you can still include them in case you add more options in the future. So you’d use [] for no options, [.repeat] for a single option, and [.repeat, .autorepeat] for multiple options.

Build and run again. This time, the password field just can’t make up its mind about staying on the screen!

Animation Easing

In real life, things don’t just suddenly start or stop moving. Physical objects like cars or trains slowly accelerate until they reach their target speed and, unless they hit a brick wall, they gradually slow down again until they come to a complete stop at their final destination.

The image below illustrates this concept:

Animation Easing

To make your animations look more realistic, you can apply the same effect of building momentum at the beginning and slowing down before the end. These are generally known as ease-in and ease-out.

You can choose from four different easing options:

  • .curveLinear: This option applies no acceleration or deceleration to the animation.
  • .curveEaseIn: Applies acceleration to the start of your animation.
  • .curveEaseOut: This option applies deceleration to the end of your animation.
  • .curveEaseInOut: Applies acceleration to the start of your animation and deceleration to the end of your animation.

To better understand how these options add visual impact to your animation, try a few of the options in your project.

Ease Out

Modify the animation code for your password field once again with a new option:

UIView.animate(withDuration: 0.5,
               delay: 0.4,
               options: [.repeat, .autoreverse, .curveEaseOut],
               animations: { [weak self] in
  }, completion: nil)

Build and run. Notice how smoothly the field decelerates until it reaches its rightmost position, before it returns to the left side of the screen:

Ease Out

This looks much more natural since that’s how things move in the real world.

Ease In

Now, try the opposite. Ease-in the animation when the field is still outside of the screen by modifying the same code as above to change the .curveEaseOut option to .curveEaseIn:

UIView.animate(withDuration: 0.5, delay: 0.4, 
  options: [.repeat, .autoreverse, .curveEaseIn], 
  animations: {[weak self] in
  completion: nil

Build and run. Observe how the field jumps back from its rightmost position with robotic vigor. This looks unnatural and isn’t as visually pleasing as the previous animation.

Finally, give .curveEaseInOut a try. It combines the two options you’ve already used into one natural-looking easing. .curveEaseInOut is the default easing function UIKit applies to your animations.

You’ve seen how the various animation options affect your project and how to make movements look smooth and natural.

Before you move on, change the options on the piece of code you’ve been playing with:

UIView.animate(withDuration: 0.5,
               delay: 0.4,
               animations: { [weak self] in
  }, completion: nil)

When there are no options for your animation, you can simply omit that parameter instead of passing an empty array.

Where to Go From Here?

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

Now that you know how basic animations work, you’re ready to tackle some more dazzling animation techniques.

Animating views from point A to point B? Pshaw — that’s so easy!

If you enjoyed what you learned in this tutorial, why not check out the complete iOS Animations by Tutorials book, available in our store?

Here’s a taste of what’s in the book:

View Animations: View animations can easily animate almost any view element and change its size, position and color.

Auto Layout: Get a crash course in Auto Layout and the animation techniques that play nicely with Auto Layout.

Layer Animations: Views on iOS are backed by layers, which offer a lower-level interface for the visual content of your apps. You’ll learn how to gain more flexibility using layers and the Core Animation API.

View Controller Transitions: Animating views and layers is impressive, but you can dial it up to 11 and animate entire view controllers! You’ll learn techniques for transitioning between view controllers and changes in device orientations, all in the same view controller.

Animations with UIViewPropertyAnimator: Learn how to create interactive, interruptible view animations. When you run animations via an animator, you can pause, stop, reverse and alter the speed of animations that are already running.

3D Animations: In this section, you’ll move beyond two dimensions and learn about 3D animations and effects with CATransform3D. Although Core Animation isn’t a true 3D framework, it lets you position things in 3D-space and set perspective – which leads to some very slick and impressive effects!

Further Types of Animations: Two more animation techniques are part of Core Animation and UIKit, but don’t fit into Sections I and III. In this section, you’ll get an impressive snowy effect working with particle emitters, and then learn about Flipbook-style frame animation with UIImageView.

I hope you enjoyed reading this tutorial. If you have any questions or comments, please join the discussion below! :]