UIView Animations in Swift
Tags: uiview, ios, swift, animations
Published: 2021-04-14 15:10:06

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:

```swift
/* 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)?)
```


```swift
/* Animate changes to one or more views using the specified duration and completion handler. */
class func animate(withDuration: TimeInterval, animations: () -> Void, completion: ((Bool) -> Void)?)
```

```swift 
/* Animate changes to one or more views using the specified duration. */
class func animate(withDuration: TimeInterval, animations: () -> Void)
```
---

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

![I am excited, are you?](https://media.giphy.com/media/5GoVLqeAOo6PK/giphy.gif)

You can download the starter project from [here](https://github.com/midhetfatema94/CustomAnimationsStarter).

---

Our first task is to animate the _welcome labels_ to behave like this:

![Animation preview for welcome labels](https://media.giphy.com/media/68qBVvUPHLZ88CGfM7/giphy.gif)

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

```swift
@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
        }
    }
}
```
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:

```swift
@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
        })
    })
}
```
![Result of the checkbox animation](https://media.giphy.com/media/G2mdaFUxt0jmmNgVJp/giphy.gif)

---

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

![Tabs animation preview](https://media.giphy.com/media/e0eZqiUxVizvhKTRQy/giphy.gif)

<!-- TODO: Check Segmented control. -->

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`

```swift
//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
}
```
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:

```swift
@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)
    }
}
```

---

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

![That's all Folks!](https://media.giphy.com/media/Og0MpQBcZYuAw/giphy.gif)

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