Take your animations to the next level with Airbnb framework, Lottie.

http://startappstudio.com/

Disclaimer: This post is based on the great tutorials on Lottie animation of Brian Advent, if you are learning iOS I strongly suggest checking out his youtube channel.

Complex animations are not an easy task, even for any experienced developer but thanks to the cool people from Airbnb now we can add incredible animations to our apps with just a few lines of code.

Lottie is an iOS, macOS, Android, and React Native library built by the people from Airbnb that renders After Effects animations in any native app.

The way to do it is to export your animations as JSON files using After Effects extension called Bodymovin, it’s very simple to use and you can see how to on this link.

If by now you are saying, “Dude, I don’t have After Effects on my computer come on!” ..it’s okay you can talk with your designer or hire one and ask him to make an animation and send you the JSON file if you are still mad at me thinking… “Come on man I don’t want to hire a designer for this!” that’s ok too, here is a link to a collection of free high-quality animations ready to be downloaded in JSON format for you.

Now that you have a JSON file selected like this one, create a new Xcode project and add it to your bundle, your JSON file will look something like this.

Next, we will use CocoaPods to add the framework to the app, (I will assume that this is not your first time using CocoaPods and that you have the dependency manager already installed on your computer) so open your terminal go inside your projects directory and create a pod file.

pod init

Add the pod to your pod file.

pod 'lottie-ios'

install it by typing the following command on your terminal.

pod install

Now that you already installed the framework to your app let’s start, go to your viewController file and import Lottie…

import Lottie

Next, add a Button at the bottom of your ViewController using the interface builder and connect an action to your ViewController’s file then copy and paste this inside your IBAction…

@IBAction func showAnimation(_ sender: Any) {
guard let animationView = LOTAnimationView(name: "bounching_ball") else {
return
}
animationView.frame = CGRect(x: 0, y: 0, width: 400, height: 400)
animationView.center = self.view.center
animationView.contentMode = .scaleAspectFill
animationView.animationSpeed = 0.8
animationView.loopAnimation = true
view.addSubview(animationView)
animationView.play()
}

So, what’s going on here? well this is all the code you need to display the animation, Lottie Framework has a class called LOTAnimationView that has a convenient initializer that takes a file name as an argument for initialization, it is a subClass of UIView and like it’s parent class you can add it to any view, it has properties that can be set like for perform a loop in the animation or change the speed of it. Finally, the “play” call triggers the animation, now run the app and tap the button.

Pretty awesome right? can you imagine how many hours you will spend looking at StackOverflow to do something like this?

Well let’s do another but now let’s create one that let the user interact with, we are going to use two files this time, that will switch the state of a button and perform an animation accordingly, download the files called buttonOn and buttonOff and again add them to your app’s bundle.

Now add a new viewController on interface builder, create a class for it called Animation2VC and connect a segue between the existing controllers, you can also just start another project but you will have to add the framework again to it.

Go to your Animations2VC file and import Lottie

import Lottie

This animation it’s going to require a little bit more of code from our side but it will be pretty straight forward, and we will do it step by step.

Step 1, declare these global properties:

var menuOn = false
var menuButton: LOTAnimationView?
var itemButtonFrame = CGRect(x: 0, y: 70, width: 100, height: 100)

Step 2, we are going to create a helper method that will add a gesture recognizer to the menuButton, copy and paste…

func addToggleRecognizer(_ animationView: LOTAnimationView) {
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(toggleMenu(recognizer:)))
animationView.addGestureRecognizer(tapRecognizer)
}

This method takes as a parameter an instance of LOTAnimationView and adds a gesture recognizer to it, it has a toggleMenu() selector and we will implement it in step 4, by now let’s just ignore the compiler error.

Step 3, technically we need to perform two different animations for each state and for that we are going to need to “reset” the menuButton view before we perform the next animation, copy and paste.

func addMenuButton(_ on: Bool) {
//if exists "reset" the state to nil
if menuButton != nil {
self.menuButton?.removeFromSuperview()
self.menuButton = nil
}

let animation = menuOn ? "buttonOff" : "buttonOn"
menuButton = LOTAnimationView(name: animation)
guard let menuButton = menuButton else {
return
}
menuButton.isUserInteractionEnabled = true
menuButton.frame = itemButtonFrame
menuButton.contentMode = .scaleAspectFill
addToggleRecognizer(menuButton)
view.addSubview(menuButton)
}

First, we check if the menuButton is not nil, if not we set it to nil and remove it from the superView, then based on our boolean menuOn we toggle between our files and then if it can be successfully initialized we proceed to add the gesture recognizer again to it.

Step 4, we are going to create a method that will handle the gesture recognizer and two helper methods to make our code clean, copy and paste…

func toggleMenu(recognizer: UITapGestureRecognizer) {
menuOn ? setMenuOffAndPerformAction() : setMenuOnAndPerformAction()
}
func setMenuOnAndPerformAction() {
menuButton?.play(completion: { (success) in

self.menuOn = true
self.addMenuButton(self.menuOn)
DispatchQueue.main.async {
print("menu is ON")
//update UI on main thread
}
})
}
func setMenuOffAndPerformAction() {

menuButton?.play(completion: { (success) in
self.menuOn = false
self.addMenuButton(self.menuOn)
DispatchQueue.main.async {
print("menu is OFF")
//update UI on main thread
}
})
}

The toggleMenu method performs an action based on the menuOn boolean if true performs the setMenuOffAndPerformAction() that triggers the play method with completion handler and inside of the closure we set the menuOn to false and we call the addMenuButton() again; if false it calls the setMenuOnAndPerformAction() that basically does the same but this time we set the menuOn to true, now run the app and tap on the button.

Now we have a cool button that handles two different states with not that many lines of code. Let’s do one more but this time let’s do something cooler, an animation for a tutorial feature in an app.

Now add a new View Controller using interface builder and create a class called Animations3VC for it, add a segue from Animation2VC to will navigate to it (again you can just create a new project if you want and add the framework again).

On interface builder on your new View Controller add a scrollView at the bottom, pin it to the left, right, and bottom and set the height to 180, finally change the background color of the scrolView and check the Paging enabled box, it should look something like this…

Open the assistant editor and go to the Animation3VC file and connect an outlet from the scrollView.

Now that your scrollView is connected to your file we are going to go again step by step…

Step 1, import Lottie into the file one last time, and add this file to your bundle’s app.

import Lottie

Step 2, we are going to declare two global properties…

let animationView = LOTAnimationView(name: "tutorial")
let dataSourceArray = ["Swipe left to begin", "Don't forget to make your bed", "Clean your toilet", "And windows", "Make a snack", "And go!"]

The first one is an instance of LOTAnimationView initialized with the “tutorial” file that you just add to your bundle’s app, the second one is an array of strings that we will use to add content to our tutorial on step 4.

Step 3, we are going to need to use one method of the UIScrollviewDelegate protocol so go to the top of your Animation3VC and make it conform to the protocol like so…

class Animation3VC: UIViewController, UIScrollViewDelegate { }

Step 4, we are going to set up the scrollView and add a label to it that will display the content of the dataSourceArray, copy and paste…

func setUpScrollView() {
tutorialScrollView.delegate = self
tutorialScrollView.contentSize = CGSize(width: self.view.frame.width * 6, height: 0)

for i in 0...dataSourceArray.count - 1 {
let labelWidth: CGFloat = 300
let positionX = ((self.view.frame.width - labelWidth) / 2) + CGFloat(i) * self.view.frame.width
let label = UILabel(frame: CGRect(x: positionX, y: 0, width: labelWidth, height: 30))
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 18, weight: 10)
label.textColor = .white
label.text = dataSourceArray[i]
tutorialScrollView.addSubview(label)
}
}

On these lines we set the delegate to the viewController and set the content size width of the scrollView to the width of the view multiplied by 6, this is because our tutorial animation has 6 states and we will need an effect of pagination for each of them.

Next, we need to add a label for each page of the scrollView that will present a text from our dataSourceArray based on an index, for that we create a loop and inside of it there are two constants, one that holds the width of each label and the other one holds a calculation to make each label be centered, and finally we set the text based on the index “i”, finally it’s added as a subview to the scrollView.

Step 5, let’s set the animationView property….

func setAnimationView() {      
guard let animationView = self.animationView else { return }
animationView.frame = CGRect(x: 0, y: 110, width: self.view.frame.size.width, height: 300)
animationView.contentMode = .scaleAspectFill
view.addSubview(animationView)
setUpScrollView()
}

By now you should be aware of what’s going on here, we just set the frame of the animationView property like we did in our past animations, we add it to the view and finally, we are calling the setUpScrollView function.

Step 6, now we need to track the progress of the animation like so…

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let progress = scrollView.contentOffset.x / scrollView.contentSize.width
animationView?.animationProgress = progress
}

Here we are using one of the methods from the UIScrollViewDelegate that gets triggered every time the user scrolls. The LOTAnimationView has a property called “animationProgress” of type CGFloat that based on the value assigned will make the animation perform a “transition”, for the a value we are dividing the contenOffset.x of the scrollView by the full width of its contentSize (if you are not sure what’s the contentOffset of the scrollView please check its documentation).

Final step! lets call setAnimationView in viewDidLoad!

override func viewDidLoad() {
super.viewDidLoad()
setAnimationView()
}

Now run the app and you should be able to see the tutorial animation.

In this post I wanted to share with you this amazing framework from Airbnb, I am already implementing it in one of my apps and the time that it saved me it’s unbelievable.

I am sure that you will enjoy working with this as well, here is the repo containing the sample project for this tutorial.

If you want to see more tutorials like this follow me on Medium or on Twitter.

Peace!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.