How to draw a circle in iOS Swift?

let block = UIView(frame: CGRectMake(cellWidth-25, cellHeight/2-8, 16, 16)) block.backgroundColor = UIColor(netHex: 0xff3b30) block.layer.cornerRadius = 9 block.clipsToBounds = true 

This is what I have right now, but it is obviously not the right way to do it.

What is the easiest way to do this?

+66
ios swift
Apr 13 '15 at 23:59 on
source share
8 answers

WARNING! This is a wrong decision - layers are added endlessly in the drawing method (every time a view is drawn). You should never add layers in a drawing method. Use layoutSubview

You can draw a circle with this:

Swift 2.2 :

  let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100,y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.CGPath //change the fill color shapeLayer.fillColor = UIColor.clearColor().CGColor //you can change the stroke color shapeLayer.strokeColor = UIColor.redColor().CGColor //you can change the line width shapeLayer.lineWidth = 3.0 view.layer.addSublayer(shapeLayer) 

Swift 3.0 :

  let circlePath = UIBezierPath(arcCenter: CGPoint(x: 100, y: 100), radius: CGFloat(20), startAngle: CGFloat(0), endAngle: CGFloat(Double.pi * 2), clockwise: true) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath //change the fill color shapeLayer.fillColor = UIColor.clear.cgColor //you can change the stroke color shapeLayer.strokeColor = UIColor.red.cgColor //you can change the line width shapeLayer.lineWidth = 3.0 view.layer.addSublayer(shapeLayer) 

With the code you posted, you crop the corners of a UIView without adding a circle to the view.




Here is a complete example of using this method:

 // make the UIView a ring of color import UIKit class Ring:UIView { override func drawRect(rect: CGRect) { drawRingFittingInsideView() } internal func drawRingFittingInsideView()->() { let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2) let desiredLineWidth:CGFloat = 1 // your desired value let circlePath = UIBezierPath( arcCenter: CGPoint(x:halfSize,y:halfSize), radius: CGFloat( halfSize - (desiredLineWidth/2) ), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.CGPath shapeLayer.fillColor = UIColor.clearColor().CGColor shapeLayer.strokeColor = UIColor.redColor().CGColor shapeLayer.lineWidth = desiredLineWidth layer.addSublayer(shapeLayer) } } 

enter image description here




Please note that there is an incredibly convenient call.

let circlePath = UIBezierPath (ovalInRect: rect)

which does all the work of creating a path. (Remember to insert it for line thickness, which is also incredibly simple with CGRectInset .)

 internal func drawRingFittingInsideView(rect: CGRect)->() { let desiredLineWidth:CGFloat = 4 // your desired value let hw:CGFloat = desiredLineWidth/2 let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) ) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.CGPath shapeLayer.fillColor = UIColor.clearColor().CGColor shapeLayer.strokeColor = UIColor.redColor().CGColor shapeLayer.lineWidth = desiredLineWidth layer.addSublayer(shapeLayer) } 

enter image description here




In practice these days in Swift, you will probably use

@IBDesignable

and

@IBInspectable

Thus, you can see and change the rendering in the storyboard!

As you can see, it actually adds new features to the Inspector on the storyboard, which you can change on the storyboard:

enter image description here

Here is the code ...

 // Dot with border, which you can control completely in Storyboard import UIKit @IBDesignable class Dot:UIView { @IBInspectable var mainColor: UIColor = UIColor.blueColor() { didSet { print("mainColor was set here") } } @IBInspectable var ringColor: UIColor = UIColor.orangeColor() { didSet { print("bColor was set here") } } @IBInspectable var ringThickness: CGFloat = 4 { didSet { print("ringThickness was set here") } } @IBInspectable var isSelected: Bool = true override func drawRect(rect: CGRect) { let dotPath = UIBezierPath(ovalInRect:rect) let shapeLayer = CAShapeLayer() shapeLayer.path = dotPath.CGPath shapeLayer.fillColor = mainColor.CGColor layer.addSublayer(shapeLayer) if (isSelected) { drawRingFittingInsideView(rect) } } internal func drawRingFittingInsideView(rect: CGRect)->() { let hw:CGFloat = ringThickness/2 let circlePath = UIBezierPath(ovalInRect: CGRectInset(rect,hw,hw) ) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.CGPath shapeLayer.fillColor = UIColor.clearColor().CGColor shapeLayer.strokeColor = ringColor.CGColor shapeLayer.lineWidth = ringThickness layer.addSublayer(shapeLayer) } } 



Finally, note that if you have a UIView (which is square in shape and which you set to say red on the storyboard) and you just want to turn it into a red circle, you can simply do the following:

 // It makes a UIView into a circular dot of color import UIKit class Dot:UIView { override func layoutSubviews() { layer.cornerRadius = bounds.size.width/2; } } 
+196
Apr 14 '15 at
source share

If you want to use UIView to draw it, you need to make a radius / height or width.

so just change:

 block.layer.cornerRadius = 9 

at

 block.layer.cornerRadius = block.frame.width / 2 

You will need to make the height and width the same. If you want to use coregraphics, then you will want to do something like this:

 CGContextRef ctx= UIGraphicsGetCurrentContext(); CGRect bounds = [self bounds]; CGPoint center; center.x = bounds.origin.x + bounds.size.width / 2.0; center.y = bounds.origin.y + bounds.size.height / 2.0; CGContextSaveGState(ctx); CGContextSetLineWidth(ctx,5); CGContextSetRGBStrokeColor(ctx,0.8,0.8,0.8,1.0); CGContextAddArc(ctx,locationOfTouch.x,locationOfTouch.y,30,0.0,M_PI*2,YES); CGContextStrokePath(ctx); 
+7
Apr 14 '15 at 0:13
source share

Make a UIView class and assign it this code for a simple circle

 import UIKit @IBDesignable class DRAW: UIView { override func draw(_ rect: CGRect) { var path = UIBezierPath() path = UIBezierPath(ovalIn: CGRect(x: 50, y: 50, width: 100, height: 100)) UIColor.yellow.setStroke() UIColor.red.setFill() path.lineWidth = 5 path.stroke() path.fill() } } 
+4
Dec 09 '17 at 21:23
source share

@Dario code update for Xcode 8.2.2, Swift 3.x. Noting that in the storyboard, set the background color to "clear" to avoid the black background in the UIView square:

 import UIKit @IBDesignable class Dot:UIView { @IBInspectable var mainColor: UIColor = UIColor.clear { didSet { print("mainColor was set here") } } @IBInspectable var ringColor: UIColor = UIColor.clear { didSet { print("bColor was set here") } } @IBInspectable var ringThickness: CGFloat = 4 { didSet { print("ringThickness was set here") } } @IBInspectable var isSelected: Bool = true override func draw(_ rect: CGRect) { let dotPath = UIBezierPath(ovalIn: rect) let shapeLayer = CAShapeLayer() shapeLayer.path = dotPath.cgPath shapeLayer.fillColor = mainColor.cgColor layer.addSublayer(shapeLayer) if (isSelected) { drawRingFittingInsideView(rect: rect) } } internal func drawRingFittingInsideView(rect: CGRect)->() { let hw:CGFloat = ringThickness/2 let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw,dy: hw) ) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = ringColor.cgColor shapeLayer.lineWidth = ringThickness layer.addSublayer(shapeLayer) } } 

And if you want to control the starting and ending angles:

 import UIKit @IBDesignable class Dot:UIView { @IBInspectable var mainColor: UIColor = UIColor.clear { didSet { print("mainColor was set here") } } @IBInspectable var ringColor: UIColor = UIColor.clear { didSet { print("bColor was set here") } } @IBInspectable var ringThickness: CGFloat = 4 { didSet { print("ringThickness was set here") } } @IBInspectable var isSelected: Bool = true override func draw(_ rect: CGRect) { let dotPath = UIBezierPath(ovalIn: rect) let shapeLayer = CAShapeLayer() shapeLayer.path = dotPath.cgPath shapeLayer.fillColor = mainColor.cgColor layer.addSublayer(shapeLayer) if (isSelected) { drawRingFittingInsideView(rect: rect) } } internal func drawRingFittingInsideView(rect: CGRect)->() { let halfSize:CGFloat = min( bounds.size.width/2, bounds.size.height/2) let desiredLineWidth:CGFloat = ringThickness // your desired value let circlePath = UIBezierPath( arcCenter: CGPoint(x: halfSize, y: halfSize), radius: CGFloat( halfSize - (desiredLineWidth/2) ), startAngle: CGFloat(0), endAngle:CGFloat(Double.pi), clockwise: true) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = ringColor.cgColor shapeLayer.lineWidth = ringThickness layer.addSublayer(shapeLayer) } } 
+2
May 26 '17 at 19:58
source share

Swift 4 version of the accepted answer:

 @IBDesignable class CircledDotView: UIView { @IBInspectable var mainColor: UIColor = .white { didSet { print("mainColor was set here") } } @IBInspectable var ringColor: UIColor = .black { didSet { print("bColor was set here") } } @IBInspectable var ringThickness: CGFloat = 4 { didSet { print("ringThickness was set here") } } @IBInspectable var isSelected: Bool = true override func draw(_ rect: CGRect) { let dotPath = UIBezierPath(ovalIn: rect) let shapeLayer = CAShapeLayer() shapeLayer.path = dotPath.cgPath shapeLayer.fillColor = mainColor.cgColor layer.addSublayer(shapeLayer) if (isSelected) { drawRingFittingInsideView(rect: rect) } } internal func drawRingFittingInsideView(rect: CGRect) { let hw: CGFloat = ringThickness / 2 let circlePath = UIBezierPath(ovalIn: rect.insetBy(dx: hw, dy: hw)) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = ringColor.cgColor shapeLayer.lineWidth = ringThickness layer.addSublayer(shapeLayer) } } 
+2
Nov 16 '18 at 10:22
source share

I find Core Graphics quite simple for Swift 3 :

 if let cgcontext = UIGraphicsGetCurrentContext() { cgcontext.strokeEllipse(in: CGRect(x: center.x-diameter/2, y: center.y-diameter/2, width: diameter, height: diameter)) } 
+1
Feb 01 '18 at 6:01
source share

Add to view done upload

  //Circle Points var CircleLayer = CAShapeLayer() let center = CGPoint (x: myCircleView.frame.size.width / 2, y: myCircleView.frame.size.height / 2) let circleRadius = myCircleView.frame.size.width / 2 let circlePath = UIBezierPath(arcCenter: center, radius: circleRadius, startAngle: CGFloat(M_PI), endAngle: CGFloat(M_PI * 4), clockwise: true) CircleLayer.path = circlePath.cgPath CircleLayer.strokeColor = UIColor.red.cgColor CircleLayer.fillColor = UIColor.blue.cgColor CircleLayer.lineWidth = 8 CircleLayer.strokeStart = 0 CircleLayer.strokeEnd = 1 Self.View.layer.addSublayer(CircleLayer) 
0
Jun 11 '18 at 8:51
source share

A simple function to draw a circle in the middle of your window frame using a percentage multiplier

 /// CGFloat is a multiplicator from self.view.frame.width func drawCircle(withMultiplicator coefficient: CGFloat) { let radius = self.view.frame.width / 2 * coefficient let circlePath = UIBezierPath(arcCenter: self.view.center, radius: radius, startAngle: CGFloat(0), endAngle:CGFloat(Double.pi * 2), clockwise: true) let shapeLayer = CAShapeLayer() shapeLayer.path = circlePath.cgPath //change the fill color shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = UIColor.darkGray.cgColor shapeLayer.lineWidth = 2.0 view.layer.addSublayer(shapeLayer) } 
0
Nov 27 '18 at 19:21
source share



All Articles