Question

I am trying to create a 200px square with rounded corners to use as an IOS toast style indication.

I have the following so far -

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1].CGColor);
    CGContextMoveToPoint(context, 10, 0);
    CGContextAddLineToPoint(context, 95, 0);
    CGContextAddArcToPoint(context, 100, 0, 100, 5, 10);
    CGContextAddLineToPoint(context, 100, 95);
    CGContextAddArcToPoint(context, 100, 100, 95, 100, 10);
    CGContextAddLineToPoint(context, 5, 100);
    CGContextAddArcToPoint(context, 0, 100, 0, 95, 10);
    CGContextAddLineToPoint(context, 0, 5);
    CGContextAddArcToPoint(context, 0, 0, 5, 0, 10);
    CGContextFillPath(context);
}

I got this far by following a tutorial - it draws a perfect 100px with rounded corners square - but I need a 150px square! I have changed every setting imaginable - with some bizzare results - but cant work out how the width height is defined!? Can anyone advise?

Was it helpful?

Solution

Update for Swift:

The below answer was correct that the time it was written for simple use cases. Things have changed a lot since then so heres an updated answer for swift.

You can create a UIView extension, to add methods to round all corners, or round specific corners. Adding @IBInspectable to the first property means it can be used in interface builder without requiring code

The second function is more complicated and can't be used as an @IBInspectable directly. It will need to be called inside the viewDidLayoutSubviews of the parent to ensure the mask doesn't cut off content as AutoLayout grows / shrinks the content.

extension UIView {

    @IBInspectable public var cornerRadius: CGFloat {
        set {
            layer.cornerRadius = newValue
        }
        get {
            return layer.cornerRadius
        }
    }

    public func roundCorners(corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        layer.mask = mask
    }
}

Once added to your project you can simply do:

myView.cornerRadius = 4

or

myView.roundCorners(corners: [.topLeft, .topRight], radius: 4)

Very old Objective-c answer:

If you import QuartzCore framework:

#import <QuartzCore/QuartzCore.h>

and add it to your project, you can use the below:

UIView *temp = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
temp.layer.cornerRadius = 5;

OTHER TIPS

If you must draw in drawRect and other stuff will be drawn in future, then just use bezierpath, otherwise see Simon's answer for simple rounded corners on a view

- (void)drawRect:(CGRect)rect {
       [super drawRect:rect];
       [[UIColor blueColor] setFill];
       UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect /*CGRectMake(0, 0, 150, 150)*/ cornerRadius:10.0];
       [path fill];
}
  1. Convert numbers to variables/constants.

  2. Change variables/constants values.

  3. Profit!

Here's your code, modified to show what I mean (untested):

- (void)drawRect:(CGRect)rect {
    static CGFloat length = 100;
    static CGFloat rounding = 5;

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1].CGColor);
    CGContextMoveToPoint(context, rounding * 2, 0);
    CGContextAddLineToPoint(context, length - rounding, 0);
    CGContextAddArcToPoint(context, length, 0, length, rounding, rounding * 2);
    CGContextAddLineToPoint(context, length, length - rounding);
    CGContextAddArcToPoint(context, length, length, length - rounding, length, rounding * 2);
    CGContextAddLineToPoint(context, rounding, length);
    CGContextAddArcToPoint(context, 0, length, 0, length - rounding, rounding * 2);
    CGContextAddLineToPoint(context, 0, rounding);
    CGContextAddArcToPoint(context, 0, 0, rounding, 0, rounding * 2);
    CGContextFillPath(context);
}

I also wonder about the 10s in your code. As far as I can see they should be 5s instead. Anyways, the easier solution is to use a UIBezierPath as others have demonstrated (the layer solution does work, but it obviously won't work if you for example want to draw something below the rounded rect and something above it).

Why don't you use a bezier path?

CGFloat radius =  4;
CGRect rect = CGRectMake(0,0,200,200);
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
[[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.1] setFill];
[path fill];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top