Journal of a Maker

A technical and personal blog by Warren C. Moore, iOS Developer

UIView Rounded Corners

This is just a quick note regarding UIViews and rounded corners.

As you may know, every UIView is backed by a stack of CALayers, a by-product of the fact that compositing in iOS is managed by Core Animation. This allows you to configure a custom masking layer on top of the primary backing layer of a view.

In the past, I’ve used Björn Sållarp’s UIImage categories to redraw images with corners as needed, with a little bit of custom magic to select which corners are rounded.

Although it is probably more performant to render an image once than composite it every time the view draws, being able to instantly select which corners are rounded is sometimes an affordable luxury. You might disagree, and Michael Ayers has done some recent work on squeezing performance out of situations like this.

But, with the goal of keeping things simple and dynamic in mind, I created a very small category on UIView that allows you to select a corner radius and a set of corners to round. The core algorithm is shown below, followed by a link to the public github repo.

1
2
3
4
5
6
7
8
9
10
11
12
13
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, nil, minx, midy);
CGPathAddArcToPoint(path, nil, minx, miny, midx, miny, (corners & UIViewRoundedCornerUpperLeft) ? radius : 0);
CGPathAddArcToPoint(path, nil, maxx, miny, maxx, midy, (corners & UIViewRoundedCornerUpperRight) ? radius : 0);
CGPathAddArcToPoint(path, nil, maxx, maxy, midx, maxy, (corners & UIViewRoundedCornerLowerRight) ? radius : 0);
CGPathAddArcToPoint(path, nil, minx, maxy, minx, midy, (corners & UIViewRoundedCornerLowerLeft) ? radius : 0);
CGPathCloseSubpath(path);

CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
[maskLayer setPath:path];
[[self layer] setMask:nil];
[[self layer] setMask:maskLayer];
[maskLayer release];

View code on Github. Feel free to fork away and send suggestions. MIT License.