Creating Youtube Style Loading Animation

Arjun Baru
The Startup
Published in
4 min readAug 25, 2020

Custom loading animation for you apps

Photo by Igor Kasalovic on Unsplash

Overview

In this tutorial we will be building a shimmer animation which can be used as a placeholder view for time when your app is busy fetching data through API or some background process.

This type of loading was introduced by Facebook and now commonly seen in apps like Youtube and Instagram as well.

If you want your app to stand out, this is the new normal.

What are we building ?

A custom animation view, which can act like a placeholder till the time API returns response.

Our final product will look something like this:

Note: GIF’s have quality limitations.

Getting Started

Download the Final Project from here.

Let’s look into the project. For creating shimmer effect we will be working with GradientLayer and CABasicAnimation

Extend UIView and add the below code:

extension UIView {
func applyShimmerEffect() {
//1let light = backgroundColor?.withAlphaComponent(0.5).cgColor ?? UIColor(red: 0, green: 0, blue: 0, alpha: 0.1).cgColorlet dark = UIColor.clear.cgColorlet shimmerGradientLayer = CAGradientLayer()shimmerGradientLayer.colors = [light, dark]shimmerGradientLayer.frame = CGRect(
x: -bounds.width,
y: 0,
width: 50 * bounds.size.width,
height: bounds.size.height
)
shimmerGradientLayer.startPoint = CGPoint(x: 0.0, y: 0)
shimmerGradientLayer.endPoint = CGPoint(x: 1.0, y: 0)
shimmerGradientLayer.locations = [0.0, 0.1]
layer.mask = shimmerGradientLayer
//2let animation = CABasicAnimation(keyPath: "locations")animation.fromValue = [0.0, 0.1]animation.toValue = [0.1, 0.2]animation.duration = 0.7animation.repeatCount = Float.infinityanimation.autoreverses = trueshimmerGradientLayer.add(animation, forKey: "shimmer")}}

//1 We will start with creating two colours for our gradient layer. First one is Light which has colour of view with alpha of 0.5, second is a clear colour.

Create a gradient layer, add the above colours to it. Set the frame of gradient to something bigger in larger in width and placed at the a position -bounds.width .This is done to give a pulse effect when we animate the layer.

Our gradient should animate along xaxis so the start and end points are given accordingly.

location property of the gradient is animatable. We will be changing the location property to produce animation.

//2 Create a CABasicAnimation instance. We will provide toValue and fromValue to the instance, toValue should be the location property set by our gradient layer and fromValue can be according to our animation.

We are setting the repeat count to infinity as our motive is to show the animation until API returns the response. Also, to make the animation smooth and have a pulse effect, we will set autoreverses = true .

This is all we need to create a shimmer effect. Next step. Creating shimmer Cards.

Card View:

We will need a protocol Shimmerable for creating shimmer cards, add the following code —

protocol Shimmerable: UIView {var shimmerViews: [UIView] { get }}extension Shimmerable {func loadShimmer() {shimmerViews.forEach { $0.applyShimmerEffect() }}

Our card view will conform to this protocol, and will provide it the views on which shimmer needs to be applied.

Note: Our shimmer card is something which will be shown during API call. It is a placeholder which will be displayed till the time data is fetched.

Let’s create a shimmer view card, Add the following class and we will go step by step to understand it.

final class ShimmerView: UIView {override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}//1
private let titleView: UIView = {
let view = UIView()
view.layer.cornerRadius = 5
view.width(160)
view.height(25)
view.backgroundColor = .lightGray
return view
}()
private let descriptionView: UIView = {
let view = UIView()
view.layer.cornerRadius = 5
view.width(UIScreen.main.bounds.width * 0.80)
view.height(150)
view.backgroundColor = UIColor.red.withAlphaComponent(0.5)
return view
}()
}//2
extension ShimmerView {
func commonInit() {
setupUI()
setConstraints()
}
func setupUI() {
addSubview(titleView)
addSubview(descriptionView)
}
func setConstraints() {
titleView.leadingToSuperview(offset: 15)
titleView.topToSuperview(offset: 15)
descriptionView.leadingToSuperview(offset: 15)
titleView.bottomToTop(of: descriptionView, offset: -12)
}
}
//3
extension ShimmerView: Shimmerable {
public var shimmerViews: [UIView] {
return [titleView, descriptionView]
}
}

//1 We have created a ShimmerView class which is subclasses of UIView . We have add two views, title and description , on which we will be applying the shimmer effect.

//2 this extension just adds the view to superView and align them one below the other.

//3 We will now conform to protocol Shimmerable and provide the views to which we will be adding shimmer effect, in our case, title and description view.

Let’s add and connect this view to our ViewController . Open ViewController.swift and add the following code in viewDidLoad method—

override func viewDidLoad() {super.viewDidLoad()view.addSubview(shimmerView)
shimmerView.topToSuperview(offset: 20, usingSafeArea: true)
shimmerView.width(UIScreen.main.bounds.width)
shimmerView.centerXToSuperview()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.shimmerView.loadShimmer()
}
}

Build and Run ! Also, let’s see how it looks in Dark Mode.

Note: GIF’s have quality limitations.

Awesome !! We have a placeholder for our content now and we got rid of our traditional loading style. Do you know, SwiftUI has an in-build placeholder for its properties ? well that’s a good topic for another animation tutorial.

--

--

Arjun Baru
The Startup

An iOS Engineer by profession, an Apple fanboy by ♥️