Harnessing the Power of CoreAnimations in Your iOS Project

Create a stunning visual Stopwatch by using CoreAnimation and CAShapeLayers

Shubham Singh
Mac O’Clock
7 min readJun 1, 2020

--

CoreAnimations are great and it can be used upon the layers of your views, to provide a smooth animation to views and it’s subviews and it helps in beautifying you app and also it provides a consistent user experience. Here’s a definition of CoreAnimation from the Apple Developer Docs —

Core Animation provides high frame rates and smooth animations without burdening the CPU and slowing down your app. Most of the work required to draw each frame of an animation is done for you. All you have to do is configure a few animation parameters (such as the start and end points) and tell Core Animation to start. Core Animation does the rest

I’ve started using them recently and let me tell you one thing, it’s pretty awesome. I was reluctant at first thinking it wasn’t easy, and it would require a lot of time to learn before I start using it, but I was wrong, once I started learning and applying the concepts I was able to grasp it relatively quickly.

Note — This tutorial is based on UIKit, if you use SwiftUI you can still go through it, but it has a different way of accomplishing it.

Alright, let’s look at how we can use CoreAnimations, CAShapeLayers to create a visual stopwatch.

The Stopwatch

Prerequisites

You don’t need to have in-depth knowledge of iOS app development, so feel free to follow along! All you need is a MacBook, Xcode, and some knowledge of Auto Layouts.

Introduction

A description of the Layers

A little introduction to the stopwatch we are going to create.

We are going to use 3 CAShapeLayers for the stopwatch and we’ll be animating it with CoreAnimation.

  • Track Layer — It’s the outer layer with a gray circle that displays the empty track.
  • Circle Fill Layer — It’s the layer that gets filled as the time progresses.
  • Round Layer — It’s the layer which shows the current position of the circle fill layer

We will also be using 3 sets of Timers for the stopwatch —

  • One timer which gets called every 1 second to update the seconds of the stopwatch.
  • One timer which gets called every 60 seconds to restart the Circle Fill Layer.
  • One timer is used to update the milliseconds of the stopwatch.

Tutorial

Start with creating a Single page application in Xcode and choose Storyboards as the User Interface.

Design the UI

Open Main.storyboard and set up the views

Main.storyboard — Adding the UI Components

Here is what we have used —

  • Stopwatch Container View — A UIView that will contain the stopwatch.
  • Stopwatch Time Label — A UILabel that will display the minutes and the seconds when the stopwatch is started.
  • Stopwatch Seconds Label — A UILabel that will display the milliseconds when the stopwatch is started.
  • Stopwatch Control Button — A UIButton that will be used to start / stop the stopwatch.

Write the code

Start with connecting the outlets of the view in the viewController

We’ll be using CAShapeLayers to create a layer and add it into the Container view’s layer. Here’s a little introduction to CAShapeLayer —

CAShapeLayer

A layer that draws a cubic Bezier spline in its coordinate space. The shape is composited between the layer’s contents and its first sublayer.

We will add 3 CAShapeLayer’s, 3 Timers, 3 colors and some variables to hold the seconds —

A variable initialValue is used to set the position of the Round Layer since it will be leading the Circle Fill Layer.

Now let’s customize the layers and add it to our containerView —

Let’s look at the above code —

The arcPath defines the Circular path inside the containerView, it has a radius of 140 and start angle as 0 and end angle as 360 to create a circle.

Then, we customize the Track layer

  • ArcPath defined above is assigned as the path of the track.
  • StrokeColor is used to define the color of the track.
  • LineWidth is used to specify the width of the track.
  • LineCap is used to specify the style of the stroke — circle, square or butt.
  • FillColor is used to specify the backgroundColor of the layer.

Customize the Circle Fill Layer

It’s almost same as the Track Layer with a few additional properties —

  • Stroke End is used to specify the percentage of the layer that will be filled with the stroke. It goes from 0–1( 0 % to 100%)

Customize the Round Layer

  • Stroke Start is used to specify the starting point of the stroke. It goes from 0–1.

Finally, we add all the layers to the containerView and customize the button.

Now let’s define the outlet function when the Start button is tapped —

Pretty simple, if the stopwatch started is set to false, we start the stopwatch & vice-versa.

We’ll start with the functions for the stopwatch soon, but before that here is a extension to append zeroes to the time if it’s less than 10, so that the time displayed is always in double digits —

Now go back to #1, we will add our animation variables just before the viewDidLoad function —

The strokeStartAnimation animates the strokeStart property of the layer —

  • Duration specifies the duration of the animation.
  • ToValue specifies the endValue that the animation has to reach after the duration.
  • Fillmode specfies the mode of the animation — forwards, backwards, or both.

The strokeEndAnimation animates the strokeEnd property of the layer the properties are the the same as above , the only difference being that is will target the strokeEnd Property.

The logic here is —

  • The Circle Fill Layer has strokeEnd animation applied on it, so that it fills the circle in 60 seconds.
  • The Round Layer has strokeStart and strokeEnd animation applied on it, so that it leads the Circle Fill Layer, if you don’t provide strokeStart property to this layer, it will behave like Circle Fill Layer, since the starting point is fixed.

Now, let’s look at the functions for the stopwatch —

  • The stopwatchSecondTimer has a timeInterval of 0.01 and it goes from 0 to 100 milliseconds.
  • The stopwatchTimer has a timeInterval of 1 seconds and it’s used to add seconds and minutes to the stopwatch.
  • The animation function is called initially and then after every 60 seconds with the help of stopWatchAnimationTimer.

The animateStopwatch function adds the strokeEndAnimation to Circle Fill Layer and strokeStartAnimation, strokeEndAnimation to Round Layer.

Finally, let’s look at the function to reset the stopWatch —

This function resets all the values to the inital value and removes the animations from the layers.

That’s it! We have created a nice visual Stopwatch with CAShapeLayers and CoreAnimations.

Here is the end result —

Completed Stopwatch

Conclusion

Let’s recap what we learned today.

We started with creating the stopwatch’s components in the storyboard, we added a stopwatchContainer, and UILabels to display the time and a UIButton to control the stopwatch.

Next, we declared the CAShapeLayers for the stopwatch, timers, and the variables for using the stopwatch and also 2 CABasicAnimation variables to animate the layers.

Next, in the viewDidLoad method, we customized the layers, and the button, and add it to the ContainerView.

Next, we wrote the code for controlling the stopwatch in the outlet function for the UIButton.

Finally, we wrote the functions for starting the stopwatch, which starts the timers, updates the labels, and also adds the animations to the layers. We also defined a resetStopwatch function, which resets the stopwatch.

I hope you were able to understand the concepts of CAShapeLayers, and CoreAnimation well, this is just the starting point, once you start playing with the properties of the layers and CoreAnimation, you can create many cool effects and transitions.

Thanks for reading this piece. Hope to see you again in the next article!

--

--

Shubham Singh
Mac O’Clock

iOS developer at Dailyrounds. I’m Immensely passionate about iOS & I’m also an avid UI/UX enthusiast. Connect with me on my Instagram/Twitter — @shubham_iosdev