Lottie
Primary version
Primary version
  • Introduction
  • Android
    • Basic Workflow
    • Caching and Preloading
    • Dynamic Properties
    • Images
    • Performance
    • Lottie vs AVD
    • APK size
    • Troubleshooting
    • Contributing
  • iOS/MacOS
    • Docs
      • View Controller Transitions
      • Dynamic Properties
      • Adding Views to Animation at Runtime
    • Tutorials
      • Building a Dynamic Progress Loader
    • Troubleshooting
      • Performance
      • Troubleshooting
  • React Native
    • Sample App
    • Props
    • Troubleshooting
  • Web
    • Getting started
    • Video tutorial
    • Previewing
    • Expressions
    • Troubleshooting
  • After Effects
    • Getting started
    • Install Bodymovin Plugin
      • Bodymovin settings
    • General tips & guidelines
    • Sketch/SVG/Illustrator to Lottie walkthrough
    • Advanced Illustrator to Lottie walkthrough
    • Troubleshooting
  • Supported After Effects Features
  • Other Platforms
    • Mobile
      • Xamarin
      • NativeScript
      • Titanium
      • Windows (UWP)
    • Web Frameworks
      • React
      • Vue
      • Angular
  • Troubleshooting
  • Community Showcase
Powered by GitBook
On this page
  1. iOS/MacOS
  2. Docs

Adding Views to Animation at Runtime

PreviousDynamic PropertiesNextTutorials

Last updated 7 years ago

Not only can you with Lottie, you can also add custom UI to a LOTAnimation at runtime. The example below shows some advance uses of this to create a dynamic image loader.

A Dynamic Image Loading Spinner

The example above shows a single LOTAnimationView that is set with a loading spinner animation. The loading spinner loops a portion of its animation while an image is downloaded asynchronously. When the download is complete, the image is added to the animation and the rest of the animation is played seamlessly. The image is cleanly animated in and a completion block is called.

Now, the animation has been changed by a designer and needs to be updated. All that is required is updating the JSON file in the bundle. No code change needed!

Here, the design has decided to add a 'Dark Mode' to the app. Just a few lines of code change the color of the animation at runtime.

Pretty powerful eh?

import UIKit
import Lottie

class ViewController: UIViewController {

  var animationView: LOTAnimationView = LOTAnimationView(name: "SpinnerSpin")
  var colorCallback = LOTColorValueCallback(color: UIColor.darkGray.cgColor)
  var maskOpacityCallback = LOTNumberValueCallback(number: 0)

  override func viewDidLoad() {
    super.viewDidLoad()

    // Setup our animaiton view
    animationView.contentMode = .scaleAspectFill
    animationView.frame = CGRect(x: 20, y: 20, width: 200, height: 200)

    self.view.addSubview(animationView)
    // Lets change some of the properties of the animation
    // We arent going to use the MaskLayer, so lets just hide it

    let maskKeypath = LOTKeypath(string: "MaskLayer.Ellipse 1.Transform.Opacity")
    animationView.setValueDelegate(maskOpacityCallback, for: maskKeypath)

    // All of the strokes and fills are white, lets make them DarkGrey
    animationView.setValueDelegate(colorCallback, for: LOTKeypath(string: "OuterRing.Stroke.Color"))
    animationView.setValueDelegate(colorCallback, for: LOTKeypath(string: "InnerRing.Stroke.Color"))
    animationView.setValueDelegate(colorCallback, for: LOTKeypath(string: "InnerRing.Fill.Color"))

    // Lets turn looping on, since we want it to repeat while the image is 'Downloading'
    animationView.loopAnimation = true
    // Now play from 0 to 0.5 progress and loop indefinitely.
    animationView.play(fromProgress: 0, toProgress: 0.5, withCompletion: nil)

    // Lets simulate a download that finishes in 4 seconds.
    let dispatchTime = DispatchTime.now() + 4.0
    DispatchQueue.main.asyncAfter(deadline: dispatchTime) {
      self.simulateImageDownloaded()
    }
  }

  func simulateImageDownloaded() {
    // Our downloaded image
    let image = UIImage(named: "avatar.jpg")
    let imageView = UIImageView(image: image)

    let layerKeypath = LOTKeypath(string: "TransformLayer")

    // We want the image to show up centered in the animation view at 150Px150P
    // Convert that rect to the layers animations coordinate space
    let imageRect = animationView.convert(CGRect(x: 0, y: 0, width: 150, height: 150), toKeypathLayer:layerKeypath)

    // Setup our image view with the rect and add rounded corners
    imageView.frame = imageRect
    imageView.layer.masksToBounds = true
    imageView.layer.cornerRadius = imageRect.width / 2;

    // Now we set the completion block on the currently running animation
    animationView.completionBlock = { (result: Bool) in ()
      // Add the image view to the layer named "TransformLayer"
      self.animationView.addSubview(imageView, toKeypathLayer: layerKeypath)
      // Now play the last half of the animation
      self.animationView.play(fromProgress: 0.5, toProgress: 1, withCompletion: { (complete: Bool) in
        // Now the animation has finished and our image is displayed on screen
        print("Image Downloaded and Displayed")
      })
    }

    // Turn looping off. Once the current loop finishes the animation will stop
    // and the completion block will be called.
    animationView.loopAnimation = false
  }

}

Check out the code below for an example! Download the After Effects file

here
change animations at runtime
Spinner
Spinner_Alt
Spinner_Dark