How to Create an Apple Card Payment Dial — Part 4

Hayder Al-Husseini
Dev Genius
Published in
4 min readJun 20, 2020

--

Photo by Melvin Thambi on Unsplash

Interface updates based on user interaction.

In the last part we started interacting with the dial by adding a thumb and allowing the user to drag the thumb around the dial.
In this part we’ll update the UI as the user interacts with the dial.

As the thumb moves, we need to update the figures in the middle of the dial, and the dial’s border background color. Let’s start with the figures.

The Figures

The whole point of the of this dial actually, is to update the amount that we want to fund our imaginary account!
To update the figures, in the defer closure inside thumbViewPanned(), add the following new function updateFigures() which we will define shortly. But before we do that, we need to declare three new variables to store our initial figures.

In commonInit() we'll add a new function called configureBalance(), this function will parse the balance string and set the value for baseBalance.

We’ll also change the property observer for balance to call this function as well.

With that out of the way, let’s go back to updateFigures(), here's it's definition:

Our angle was measured using atan2(), this function returns the angle in the range -CGFloat.pi < angle < CGFloat.pi.
In our dial the top half represents -CGFloat.pi and the bottom half is CGFloat.pi. The value variable is being translated so that it starts from 0. When entering the third quadrant which is where -CGFloat.pi start, we add 2PI to negate it's effect on value.
Since the first marker is our start point, we subtract it's angle from the calculated value. Now we transform value to a value between 0 and maximumFundingAmount. Finally we update our labels.

Running the app, and panning the thumb, we Should get the following result:

The Dial’s Background Color

As we drag the thumb, we want the background the thumb has passed across to have a differnet color, like so:

The dial with it’s background color being set

We achieve this effect by adding a CAGradientLayer to dialBody's layer and masking it with a CAShapeLayer that is added on top.

We need to add the following instance variables to our class:

To setup the gradient layer, we define a function called setupGradient() and call it inside commonInit().

The updateDialColors() function will change the gradients colors based on where the thumb is located in the dial, it's definition looks like this:

The updateShapeLayer() function that is called at the end of setupGradient() creates the mask on top of the gradient layer, it creates a path that follows our thumb. It's definition is:

We also add updateShapeLayer() to our updateThumb() function. That way everytime we move the thumb our shape layer is updated.

CALayer objects don't follow constraint updates. So in our updateConstraints() function we need to update our layer objects frames, like so:

To change the gradient color after passing a marker, we check if the angle is located between two markers, if it is, we set currentMarker to be the smallest marker and update the color accordingly, if and only if currentMarker has changed. This check is done in a new function updateDialColorsIfNeeded():

We call updateDialColorsIfNeeded() in the thumbViewPanned() defer closure.

To see how the gradient is masked, hide the Text View in Interface Builder and run the app. You should see the following:

Animation showing how the masking is done

Opening Main.storyboard should now look like this:

Xcode window showing the final render of the view

Running the project, should result in the following:

The Apple Card dial’s thumb has icons that update as you reach a marker. I’ll leave that to you my fellow reader as an exercise.

In the next part, we’ll see how to we’ll make our view accessibile.

--

--