August 12, 2020

Lottie animation progress in iOS

By Mohit Agrawal

How to use Lottie animation as a custom progress bar in iOS?

Introduction

Whenever we need to execute some task and it takes a considerable amount of time then its good practice to show some kind of progress bar to the user.

In my previous tutorial, I have shown you how to add Lottie animation in the iOS app. Today I will show you some advanced way of using the Lottie animation.

What we will build?

You will learn how to use Lottie animation as a progress bar (indicator) in iOS. We will create a demo app in which there will be three elements.

  1. Animation View: For the Lottie animation.
  2. UILabel: To show the download percentage in text.
  3. UIButton: To kick off the download process.

Implementation

I assume that you already know how to Integrate Lottie animation in iOS. So, I am skipping those steps.

1. Choose Lottie file

We need a Lottie JSON file which shows the progress bar. Check out this large collection and download anyone for your project.

The is the one which I am going to use: https://lottiefiles.com/16767-download-lottie

Now import the Lottie file in your iOS project and keep it ready for the next step.

2. Creation of UI

Open you Main.storyboard and create a UI similar to this.

lottie ios progress 1

It has only three UI elements as described above. Don’t worry much about the UI because our main focus will be on the logical part. Also, create the reference for all the three elements in the ViewController.swift.

3. Let’s code the logic

These are the methods and variables which we have to create in a ViewController.swift.

import UIKit
import Lottie

class ViewController: UIViewController {

    @IBOutlet weak var animationVIEW: AnimationView!
    @IBOutlet weak var progressLabel: UITextField!
    
    private var startingFrame: CGFloat = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setAnimationView()
    }
    
    //To setup the animation view
    private func setAnimationView() {
        
    }
    
    //To start the download process
    private func startDownload() {
      
    }

    @IBAction func didTapStartDownload(_ sender: Any) {
        startDownload()
    }
    
    //To set the progress of animation
    func progress(_ percentDownloaded: CGFloat) {
      
    }
}

// MARK: - Download Delegate

extension ViewController: URLSessionDownloadDelegate {
  // handles download progress
  func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
 
  }
  

  // finishes download
  func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    
  }
  
}

3.1 URLSessionDownloadDelegate

Now let’s see the use of all the methods one by one. First, let’s talk about the URLSessionDownloadDelegate.

A protocol that defines methods that URL session instances call on their delegates to handle task-level events specific to download tasks.

Apple documentation

Using this delegate, we can easily calculate the percentage of downloaded data.

urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)

totalBytesWritten: The number of bytes transferred since the last time this delegate method was called.

totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length header.

The other one tells the delegate that a download task has finished downloading.

urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)

3.2 progress(_ percentDownloaded: CGFloat)

This is another important method which you need to understand. It takes a total percent download in a float as a parameter which we will be using to set the progress of the animation view.

animationVIEW.play(fromFrame: startingFrame, toFrame: percentDownloaded*180, loopMode: .playOnce, completion: nil)

fromFrame: The start frame of the animation. If nilthe animation will start at the current frame.

toFrame: The end frame of the animation.

loopMode: The loop behavior of the animation. If nilthe view’s loopMode the property will be used.

completion: An optional completion closure to be called when the animation stops.

If you notice, I am multiplying 180 with the total downloaded percentage. It will be different for your animations. My animation competes in the 180th frame. You need to check that at what frame your animation completes its one loop.

4. Complete code

Now check the complete code for ViewController.swift. Every method should be understandable now.

//
//  ViewController.swift
//  Lottie anim
//
//  Created by Mohit Agrawal on 31/07/20.
//  Copyright © 2020 Mohit Agrawal. All rights reserved.
//

import UIKit
import Lottie

class ViewController: UIViewController {

    @IBOutlet weak var animationVIEW: AnimationView!
    @IBOutlet weak var progressLabel: UITextField!
    
    private var startingFrame: CGFloat = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        setAnimationView()
    }
    
    //To setup the animation view
    private func setAnimationView() {
        animationVIEW!.contentMode = .scaleAspectFit
        animationVIEW!.loopMode = .playOnce
    }
    
    //To start the download process
    private func startDownload() {
      let url = URL(string: "https://archive.org/download/SampleVideo1280x7205mb/SampleVideo_1280x720_5mb.mp4")!
      let configuration = URLSessionConfiguration.default
      let operationQueue = OperationQueue()
      let session = URLSession(configuration: configuration, delegate: self, delegateQueue: operationQueue)
      let downloadTask = session.downloadTask(with: url)
      downloadTask.resume()
    }

    @IBAction func didTapStartDownload(_ sender: Any) {
        startDownload()
    }
    
    //To set the progress of animation
    func progress(_ percentDownloaded: CGFloat) {
        animationVIEW.play(fromFrame: startingFrame, toFrame: percentDownloaded*180, loopMode: .playOnce, completion: nil)
        startingFrame = percentDownloaded
    }
}

// MARK: - Download Delegate

extension ViewController: URLSessionDownloadDelegate {
  // handles download progress
  func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
  
    let percentDownloaded: CGFloat = CGFloat(totalBytesWritten) / CGFloat(totalBytesExpectedToWrite)
    DispatchQueue.main.async {
        self.progressLabel.text = "Downloading: \((percentDownloaded * 100).rounded())%"
        self.progress(percentDownloaded)
    }
  }
  

  // finishes download
  func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    DispatchQueue.main.async {
        self.animationVIEW.play(fromFrame: self.startingFrame, toFrame: 241, loopMode: .playOnce, completion: nil)
    }
  }
  
}


Now your project and see the magic of Lottie animation in your iOS app. It makes the app more beautiful. If you are facing any issue or error then please let me know in the comment section.

Subscribe YouTube: More tutorials like this

I hope this blog post is useful for you, do let me know your opinion in the comment section below.
I will be happy to see your comments down below 👏.
Thanks for reading!!!