How to make rounded corners and sides in UIview programmatically like has youtube:
I know how to make rounded corner but have no idea how to make rounded sides. I need to do it programmatically (not just setting image mask previously designed)
You can create a UIBezierPath
. If you want to just round the corners, you can use bezierPathWithRoundedRect
. If you want something more sophisticated, like that YouTube logo, you would use moveToPoint
and a series of addCurveToPoint
or addQuadCurveToPoint
.
For example, this is a close approximation:
That was generated with:
// ViewController.m
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.shapeLayer = [CAShapeLayer layer];
self.shapeLayer.fillColor = [UIColor redColor].CGColor;
self.shapeLayer.strokeColor = [UIColor clearColor].CGColor;
[self.view.layer addSublayer:self.shapeLayer];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
CGFloat width = MIN(self.view.bounds.size.width, self.view.bounds.size.height * 4.0 / 3.0);
CGFloat height = width * 3.0 / 4.0;
CGSize size = CGSizeMake(width, height);
CGFloat corner = width / 9.0;
CGPoint center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
self.shapeLayer.path = [self roundedPathAtCenter:center size:size corner:corner].CGPath;
}
- (UIBezierPath *)roundedPathAtCenter:(CGPoint)center size:(CGSize)size corner:(CGFloat)corner {
CGFloat width = size.width;
CGFloat height = size.height;
UIBezierPath *path = [UIBezierPath bezierPath];
// upper left corner
[path moveToPoint: CGPointMake(center.x - width / 2.0 + corner / 2.0, center.y - height / 2.0 + corner / 2.0)];
// path to top center
[path addQuadCurveToPoint: CGPointMake(center.x, center.y - height / 2.0) controlPoint: CGPointMake(center.x - width / 2.0 + corner, center.y - height / 2.0)];
// path to upper right
[path addQuadCurveToPoint: CGPointMake(center.x + width / 2.0 - corner / 2.0, center.y - height / 2.0 + corner / 2.0) controlPoint: CGPointMake(center.x + width / 2.0 - corner, center.y - height / 2.0)];
// path to mid right
[path addQuadCurveToPoint: CGPointMake(center.x + width / 2.0, center.y) controlPoint: CGPointMake(center.x + width / 2.0, center.y - height / 2.0 + corner)];
// path to lower right
[path addQuadCurveToPoint: CGPointMake(center.x + width / 2.0 - corner / 2.0, center.y + height / 2.0 - corner / 2.0) controlPoint: CGPointMake(center.x + width / 2.0, center.y + height / 2.0 - corner)];
// path to center bottom
[path addQuadCurveToPoint: CGPointMake(center.x, center.y + height / 2.0) controlPoint: CGPointMake(center.x + width / 2.0 - corner, center.y + height / 2.0)];
// path to lower left
[path addQuadCurveToPoint: CGPointMake(center.x - width / 2.0 + corner / 2.0, center.y + height / 2.0 - corner / 2.0) controlPoint: CGPointMake(center.x - width / 2.0 + corner, center.y + height / 2.0)];
// path to mid left
[path addQuadCurveToPoint: CGPointMake(center.x - width / 2.0, center.y) controlPoint: CGPointMake(center.x - width / 2.0, center.y + height / 2.0 - corner)];
// path to top left
[path addQuadCurveToPoint: CGPointMake(center.x - width / 2.0 + corner / 2.0, center.y - height / 2.0 + corner / 2.0) controlPoint: CGPointMake(center.x - width / 2.0, center.y - height / 2.0 + corner)];
[path closePath];
return path;
}
@end
You can play around with those control points to get the effect you're looking for. The key is that you want the the first control point to be in line with the second control point of the preceding arc.
In this example, I'm just creating a CAShapeLayer
and adding it as a sublayer. Alternatively, you could take this CAShapeLayer
and add it as a mask
to the layer
of some other view, too. The key is that you just need to create a UIBezierPath
that draws the outline you want, and either just draw it, add it as a sublayer, or use it as a mask.
For Swift users:
class ViewController: UIViewController {
private var shapeLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
shapeLayer.fillColor = UIColor.red.cgColor
shapeLayer.strokeColor = UIColor.clear.cgColor
view.layer.addSublayer(shapeLayer)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
let width = min(view.bounds.width, view.bounds.height * 4 / 3) - 20
let size = CGSize(width: width, height: width * 3 / 4)
shapeLayer.path = roundedPath(center: center, size: size, corner: width / 10).cgPath
}
func roundedPath(center: CGPoint, size: CGSize, corner: CGFloat) -> UIBezierPath {
let width = size.width
let height = size.height
let path = UIBezierPath()
// upper left corner
path.move(to: CGPoint(x: center.x - width / 2 + corner / 2, y: center.y - height / 2 + corner / 2))
// path to top center
path.addQuadCurve(to: CGPoint(x: center.x, y: center.y - height / 2), controlPoint: CGPoint(x: center.x - width / 2 + corner, y: center.y - height / 2))
// path to upper right
path.addQuadCurve(to: CGPoint(x: center.x + width / 2 - corner / 2, y: center.y - height / 2.0 + corner / 2.0), controlPoint: CGPoint(x: center.x + width / 2 - corner, y: center.y - height / 2))
// path to mid right
path.addQuadCurve(to: CGPoint(x: center.x + width / 2, y: center.y), controlPoint: CGPoint(x:center.x + width / 2, y: center.y - height / 2.0 + corner))
// path to lower right
path.addQuadCurve(to: CGPoint(x: center.x + width / 2 - corner / 2, y: center.y + height / 2 - corner / 2), controlPoint: CGPoint(x: center.x + width / 2, y: center.y + height / 2 - corner))
// path to center bottom
path.addQuadCurve(to : CGPoint(x: center.x, y: center.y + height / 2), controlPoint: CGPoint(x: center.x + width / 2 - corner, y: center.y + height / 2))
// path to lower left
path.addQuadCurve(to: CGPoint(x: center.x - width / 2 + corner / 2, y: center.y + height / 2 - corner / 2), controlPoint: CGPoint(x: center.x - width / 2 + corner, y: center.y + height / 2))
// path to mid left
path.addQuadCurve(to: CGPoint(x: center.x - width / 2, y: center.y), controlPoint: CGPoint(x: center.x - width / 2, y: center.y + height / 2 - corner))
// path to top left
path.addQuadCurve(to: CGPoint(x: center.x - width / 2 + corner / 2, y: center.y - height / 2 + corner / 2), controlPoint: CGPoint(x: center.x - width / 2, y: center.y - height / 2 + corner))
path.close()
return path
}
}