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.
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.
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)];