Continuous Rounded Corners with UIKit

Benoît Layer
Jan 10 · 3 min read

At Fueled, we spent the last couple months building an awesome augmented reality game called Toppler to explore some of the capabilities of ARKit 2. We’ve already covered some of the technical lessons we leraned in two previous articles mostly related to SceneKit. Now it’s time to get back to UIKit and take a deeper look at some design concepts and their implementations for this more familiar framework.

We’ll be looking specifically at rounded corners. Not the ones you usually build with layer.cornerRadius, but continuous rounded corners. Just so we’re clear on the difference, here is a comparison between classic rounded corners and continuous rounded corners that Apple introduced back in 2013, with the release of iOS7:

Red has base corners, Orange has smoothed corners

Notice the very thin red color that you can see behind the orange view. This is the actual difference between base and smooth corners.

For those of you using Sketch, the property to design continuous corners is called Smooth Corners:

Sketch option to draw continuous (or smooth) corners

Apple uses a private API to power its rounded corners in the SpringBoard. It’s var continuousCorners: Bool from CALayer. However, if you use this API in an app that you submit to the AppStore it will be rejected. 😕

There are a number of resources on the Internet to acheive the same effect in an approved way, usually involvingUIView subclasses and their own implementation of drawRect. However, we’ve been preferring a much simpler solution, which you can apply to any UIView with the help of a mask.

It turns out that UIBezierPath(roundedRect:cornerRadius) produces a continuous corner. Simply using a CAShapeLayer whose path is built with the previous function will also do the trick:

But stopping there would not be enough since our masked view will usually be resized during animations for instance, and the mask would not evolve in the meantime, unless we update it manually. To solve this issue, we can create a UIView subclass to handle it for us.

To accomplish this, you can override the bounds property to intercept any change, update our mask, and if needed, animate the change. The key to detecting an ongoing animation is to use the animation(forKey:) function, which will return an optional running animation. We’ll copy this animation, to do our own updates, but use the same timing parameters:

Here’s a preview of what we achieved in Toppler by using these continuous corners alongside some animations and blur effects:

Toppler Settings screen

The augmented reality in Toppler represents the core experience. But we mustn’t forget the many other views that tie everything together to create a gorgeous and unique user experience. And that, my friends, always starts and ends with the ubiquitous UIKit.

Fueled Engineering

Publishing insights and discoveries on iOS and Android app development since 1982.

Benoît Layer

Written by

Senior iOS Engineer at Fueled

Fueled Engineering

Publishing insights and discoveries on iOS and Android app development since 1982.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade