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's obviously not the right way to do it.
What's the simplest way to do it?
WARNING! This is an incorrect solution. layers are added infinitely in the
drawRect
method (every time the view is drawn). You should NEVER add layers in thedrawRect
method. UselayoutSubview
instead.
You can draw a circle with this (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 have posted you are cropping the corners of the UIView
, not adding a circle to the view.
Here's a full example of using that method:
/// A special UIView displayed as a ring of color 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) } }
Note, however there's an incredibly handy call:
let circlePath = UIBezierPath(ovalInRect: rect)
which does all the work of making the path. (Don't forget to inset it for the line thickness, which is also incredibly easy 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) }
In practice these days in Swift, you would certainly use @IBDesignable
and @IBInspectable
. Using these you can actually see and change the rendering, in Storyboard!
As you can see, it actually adds new features to the Inspector on the Storyboard, which you can change on the Storyboard:
/// A dot with a border, which you can control completely in Storyboard @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, and which you set to say red in Storyboard) and you simply want to turn it in to a red circle, you can just do the following:
// Makes a UIView into a circular dot of color class Dot: UIView { override func layoutSubviews() { layer.cornerRadius = bounds.size.width/2 } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With