DEV Community

loading...

UIView Animations in Swift

Midhet Sulemani
iOS Developer by profession. Interested in UX Design, AI and Robotics. I also enjoy watching random YouTube videos, reading, going out for walks and doing some graphic design on the side.
・3 min read

Apple's documentations says that: Changes to several view properties can be animated—that is, changing the property creates an animation starting at the current value and ending at the new value that you specify.

The following properties of the UIView class are animatable:

  • frame: position of the view with respect to it's superview
  • bounds: position of the view with respect to it's own view
  • center: center point of the view with respect to it's superview
  • transform: size of the view and its orientation in the superview
  • alpha: opacity of the view
  • backgroundColor

These are some of the basic animation functions provided by Swift as an extension to UIViews:

/* Animate changes to one or more views using the specified duration, delay, options, and completion handler. */

class func animate(withDuration: TimeInterval, delay: TimeInterval, options: UIView.AnimationOptions, animations: () -> Void, completion: ((Bool) -> Void)?)
Enter fullscreen mode Exit fullscreen mode
/* Animate changes to one or more views using the specified duration and completion handler. */
class func animate(withDuration: TimeInterval, animations: () -> Void, completion: ((Bool) -> Void)?)
Enter fullscreen mode Exit fullscreen mode
/* Animate changes to one or more views using the specified duration. */
class func animate(withDuration: TimeInterval, animations: () -> Void)
Enter fullscreen mode Exit fullscreen mode

Let's start with a simple TODO application and traverse through all these animations

I am excited, are you?

You can download the starter project from here.


Our first task is to animate the welcome labels to behave like this:

Animation preview for welcome labels

In the animateEachLabel() function, we want to animate our welcome message.

@objc func animateEachLabel() {
    UIView.animate(withDuration: 1.5, animations: {
        self.welcomeLabel.frame.origin.x = 20
    }) {_ in
        UIView.an animate(withDuration: 1.5) {
            self.nameLabel.frame.origin.x = 20
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

We have nested one UIView.animate within another because we want the effect of an animation starting on the completion of other. This is also called as animation chaining.


The next animation will be a task checking animation in which will be animating the alpha of the button's image. This will also be combined with a checking/unchecking toggle as below:

@IBAction func checkingBox(_ sender: UIButton) {
    UIView.animate(withDuration: 0.2, animations: {
        sender.alpha = 0
    }, completion: {_ in
        UIView.animate(withDuration: 0.2, animations: {
            sender.isSelected = !sender.isSelected
            sender.alpha = 1
        })
    })
}
Enter fullscreen mode Exit fullscreen mode

Result of the checkbox animation


The next animation we will accomplish is a material design tabs behavior

Tabs animation preview

We will be using a horizontal scroll view and it's delegate for creating an effect on the horizontal swipe.

Add this code to your TodoListViewController

//Make an outlet for your scrollview
@IBOutlet weak var pagingScroll: UIScrollView!

//Add this line in your viewDidLoad
pagingScroll.delegate = self

//Add the following functions
func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
    let arrayIndex = Int(pageIndex)
    underlineLabel.center.x = getDraggablePoint(scrollView: scrollView)
    underlineLabel.frame.size.width = todoCategory[arrayIndex].intrinsicContentSize.width
}

func getDraggablePoint(scrollView: UIScrollView) -> CGFloat {
    let progress = scrollView.contentOffset.x / (scrollView.contentSize.width - scrollView.bounds.size.width)
    let minPoint = todoCategory.first?.center.x ?? 0
    let maxPoint = todoCategory.last?.center.x ?? 0
    let pathValue = maxPoint - minPoint
    return (pathValue * progress) + minPoint
}
Enter fullscreen mode Exit fullscreen mode

The getDraggablePoint method is going to calculate the center point of your label in the scrollview and figure out its own offset.

The UI setup of the buttons in the scrollview are given in the starter project.

You'll see that nothing is working on the click of the button, the code we wrote above is to facilitate the moving of the underline on swiping in through views.

To make the animation work on clicking of the button, add this code to the outlet of your buttons:

@IBAction func selectTodo(_ sender: UIButton) {
    //Calculating offset of the underline
    let contentOffsetPoint = sender.tag * Int(self.view.frame.width)

    //Automatically scrolling the scroll view and underline with animation
    UIView.animate(withDuration: 0.75) {
        self.pagingScroll.setContentOffset(
        CGPoint(x: contentOffsetPoint, y: 0), animated: false)
    }
}
Enter fullscreen mode Exit fullscreen mode

To see your beautiful animations in action, Build & Run!

That's all Folks!

Hope you enjoyed this tutorial, will be back with the Core Animation one soon!

Discussion (0)