Rounding Up: Rounding Select Corners on a UIView.

Posted by Grego on December 27, 2014

I think most people know how to create round all the corners of a UIView, demonstrated by the html layer below:

By using:

  view.layer.cornerRadius = 10;
  view.layer.masksToBounds = YES;

However, I wanted to create a UIView by rounding only some corners as in the following:

Solution

Turns out, it’s actually pretty simple. First I’ll show you the code, then dive in and pick it apart.

  CAShapeLayer *roundedCornerMask = [CAShapeLayer new];
  roundedCornerMask.path = [UIBezierPath bezierPathWithRoundedRect:self.roundView.bounds
                                                 byRoundingCorners:UIRectCornerTopRight | UIRectCornerBottomRight                                                       cornerRadii:CGSizeMake(10, 10)].CGPath;
  self.roundView.layer.mask = roundedCornerMask;

First, we create a CAShapeLayer :

  CAShapeLayer *roundedCornerMask = [CAShapeLayer new];

Then, we set its path to a new UIBezierPath that we create by using [UIBezierPath bezierPathWithRoundedRect:byRoundingCorners:cornerRadii:], but CAShaperLayer.path requires a CGPath, so we call [UIBezierPath CGPath] to get the resulting CGPath:

  roundedCornerMask.path = [UIBezierPath bezierPathWithRoundedRect:self.roundView.bounds
                                                 byRoundingCorners:UIRectCornerTopRight | UIRectCornerBottomRight                                                       cornerRadii:CGSizeMake(10, 10)].CGPath;

The corners to be rounded are specified by the byRoundingCorners: parameter. Possible values are:

  • UIRectCornerBottomRight
  • UIRectCornerTopRight
  • UIRectCornerTopLeft
  • UIRectCornerBottomLeft

and can be joined with a | to specify multiple corners.

Then, apply the CAShapeLayer we created as our view’s layer mask using view.layer.mask:

  self.roundView.layer.mask = roundedCornerMask;

Achieving Better Abstraction

It may not seem like a whole lot of work, but if you’re using this technique frequently enough, it’s better to abstract it out to its own class.

In essence, we want to add something to UIView. This can be accomplished by simply subclassing and creating our own UIRoundedCornerView. But if we drop this into any preexisting projects we might have, we’d have to go in and replace existing views with UIRoundedCornerView, which sounds like a lot of work to me.

Instead, we should make things easier on ourselves and use a category to effectively add our own new convenience methods to the base UIView class.

Create a new Category

Create a new category, by going to File > New File … or press ⌘ N.

new-file

For the File name I chose RoundCorners (making our category UIView+RoundCorners). Make sure to select Category for the File Type and UIView for the Class.

new-category

We can take our existing code and drop it into our new category, but now we can parametrize it:

UIView+RoundCorners.m:

#import "UIView+RoundCorners.h"

@implementation UIView (RoundCorners)
- (void)roundCorners:(UIRectCorner)corners withRadii:(CGSize)radii
{
  CAShapeLayer *roundedCornerMask = [CAShapeLayer new];
  roundedCornerMask.path = [UIBezierPath bezierPathWithRoundedRect:self.bounds
                                                 byRoundingCorners:corners
                                                       cornerRadii:radii].CGPath;
  self.layer.mask = roundedCornerMask;
}
@end

Then make it visible in the interface file.

UIView+RoundCorners.h:

#import <UIKit/UIKit.h>

@interface UIView (RoundCorners)
- (void)roundCorners:(UIRectCorner)corners withRadii:(CGSize)radii;
@end

And implement it where ever you need it:

  [self.roundView roundCorners:UIRectCornerBottomRight | UIRectCornerTopRight
                     withRadii:CGSizeMake(10, 10)];