Contact us


Custom UIActivityIndicatorView with Lottie for iOS in Swift - Enhancing App Aesthetics

August 21, 2023
Whether it's a long network API call or a resource-intensive task, having a visual cue that signifies background activity is essential. Even though Apple provides native UIActivityIndicatorView for indicating a running background task, app designers often prefer to steer away from native elements. This is especially true when crafting a unique user experience.

In this article, we'll explore the process of creating a custom solution for an activity indicator. The activity indicator will have similar functionality of Apple's UIActivityIndicatorView. By the end of our step by step guide, the result should look something like this:

Lottie Animation View

In this example, we are using a Lottie Animation View. However, the project can easily be modified to contain a custom drawn animation.

Lottie is an open-source animation library that allows developers to render complex animations created in Adobe After Effects directly in their apps. Typically, you can export Lottie animations as JSON files from After Effects using a plugin. Of course, you can later integrate these files into the app's codebase.

What's great about Lottie is its ability to bring intricate animations to apps without the need for extensive coding or performance impact. Developers can simply include the Lottie animation file in their project and use the library to display the animation with minimal effort.

For this tutorial, we'll use this Lottie animation.

Assuming you've already followed the steps in our previous blog post ''Creating a Custom Onboarding Swiper in iOS using MVVM architecture and without UIPageViewController'' to set up your project, make sure the following framework is integrated using Cocoapods:


Create the Custom Activity Indicator

To start off, let's create a custom view that covers the entire screen. We'll center the Lottie animation within this view.

import UIKit

import PureLayout

import Lottie

class CustomActivityIndicator: UIView {

private var lottieView: LottieAnimationView?

private var loaderImageName = ""

private convenience init() {

    self.init(frame: UIScreen.main.bounds)

    loaderImageName = Constants.Lottie.LOADING


private convenience init(with image: String) {

    self.init(frame: UIScreen.main.bounds)

    loaderImageName = image




Now we need to position our LottieAnimation in the centre of the screen. To make the animation stand out a bit more, we'll blur the background using Gaussian blur. This gives the user a visual cue that something has changed and the user has to wait for the loading to finish before using the application again.

private func setupUI() {

        backgroundColor = .clear

        let blurEffect = UIBlurEffect(style: .light)

        let blurView = UIVisualEffectView(effect: blurEffect)

        insertSubview(blurView, at: 0)


        self.lottieView = LottieAnimationView(name: loaderImageName)

        if let lottieView = lottieView {


            let size = self.frame.width * 0.95

            lottieView.autoSetDimensions(to: CGSize(width: size, height: size))


            lottieView.loopMode = .loop

            lottieView.contentMode = .scaleAspectFit



Add methods for funcionality

Just like with Apple's UIActivityIndicator, we'll expose methods to initiate and halt animations. This symmetry ensures that developers have familiar tools at their disposal to control animations and minimizes code changes when taking this approach.

public func startAnimating() {

        if self.lottieView == nil {


            DispatchQueue.main.async { [weak self] in





    public func stopAnimating() {

        DispatchQueue.main.async {[weak self] in




    public func isAnimating() -> Bool {

        guard let lottieView = lottieView else {

            return false


        return lottieView.isAnimationPlaying


Additionally, while the Lottie animation is active, user interaction will be disabled, preventing any unintended actions.

private func showLoadingActivity() {


        self.isUserInteractionEnabled = false


    private func startAnimation() {

        guard let lottieView = lottieView else { return }


    private func stopAnimation() {



        lottieView = nil


        self.isUserInteractionEnabled = true


Putting It All Together

To use this new is quite simple; instantiate it in a View Controller just like you would the native UIActivityIndicatorView:

lazy var activityIndicator: CustomActivityIndicator = {
        return CustomActivityIndicator()

The view doesn’t need to be added to the View Controller’s view, just call it wherever you need it. For example, after a button click, start the animation by calling .startAnimating(), and after 5 seconds turn it off by calling stopAnimating():

DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {


When you're working with designers, opting for custom elements is often the way to go. It enables you to break free from the norm and introduce custom views with minimal code changes. That’s why these views that we implement follow the same patterns and functions, ensuring a smooth integration.

By embracing custom animations and views, you're taking a simple yet impactful step toward enhancing your app's visual appeal.

Karolina Škunca

Karolina is an iOS Software Developer. She works on preventing security attacks on iOS phones and frequently tests ASEE’s applications. Her greatest passions are designing and developing new applications.

Want to learn more about cybersecurity trends and industry news?



chevron-down linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram