Reputation: 161
What is the best way to create round circles around the edges of a UIView also the circles has to be transparent i create this with sketch
Upvotes: 2
Views: 3574
Reputation: 186
I have a subclass of UIView
for such tasks. Basically, it uses CAShapeLayer
, created with UIBezierPath
, as a mask for view. You can customize frames and corner radius of holes. Here is my code:
import UIKit
struct TransparentPart {
var rect: CGRect
var cornerRadius: CGFloat
}
class PartiallyTransparentView: UIView {
var transparentParts: [TransparentPart] = []
override func draw(_ rect: CGRect) {
super.draw(rect)
backgroundColor?.setFill()
UIRectFill(rect)
let clipPath = UIBezierPath(rect: self.bounds)
for part in transparentParts {
let holeRect = part.rect
let radius = part.cornerRadius
let path = UIBezierPath(roundedRect: holeRect, cornerRadius: radius)
clipPath.append(path)
}
let layer = CAShapeLayer()
layer.path = clipPath.cgPath
layer.fillRule = kCAFillRuleEvenOdd
self.layer.mask = layer
self.layer.masksToBounds = true
}
}
Upvotes: 0
Reputation: 61
I have achieved this thing by using UIBezierPath and CAShapeLayer
I am taking outlet of view from storyboard.
@IBOutlet weak var myView: UIView!
Create an object of UIBezierPath()
var path = UIBezierPath()
Create a method which take center point of circle as parameter and we create another UIBezierPath() as circlePath which is circle and we append the circle on previous UIBezierPath() path.
Know take a CAShapeLayer and cut the circlePath
func overLay(points: CGPoint) {
let sizes = CGSize(width: 30, height: 30)
let circlePath = UIBezierPath(ovalIn: CGRect(origin: points, size: sizes))
path.append(circlePath)
let maskLayer = CAShapeLayer() //create the mask layer
maskLayer.path = path.cgPath // Give the mask layer the path you just draw
maskLayer.fillRule = kCAFillRuleEvenOdd // Cut out the intersection part
myView.layer.mask = maskLayer
}
Create updateUI() and call overLay methods with all points.
func updateUI() {
path = UIBezierPath(rect: myView.bounds)
let viewFrames = myView.bounds
overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y - 15))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y - 15))
overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y + viewFrames.height - 15))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height - 15))
overLay(points: CGPoint(x: viewFrames.origin.x - 15 , y: viewFrames.origin.y + viewFrames.height/2))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height/2))
}
call updateUI from viewDidLayoutSubviews() method.
override func viewDidLayoutSubviews() {
updateUI()
}
it will create the overlay on view with transparency.
Full code snippet
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var myView: UIView!
var path = UIBezierPath()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func overLay(points: CGPoint) {
let sizes = CGSize(width: 30, height: 30)
let circlePath = UIBezierPath(ovalIn: CGRect(origin: points, size: sizes))
path.append(circlePath)
let maskLayer = CAShapeLayer() //create the mask layer
maskLayer.path = path.cgPath // Give the mask layer the path you just draw
maskLayer.fillRule = kCAFillRuleEvenOdd // Cut out the intersection part
myView.layer.mask = maskLayer
}
override func viewDidLayoutSubviews() {
updateUI()
}
func updateUI() {
path = UIBezierPath(rect: myView.bounds)
let viewFrames = myView.bounds
overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y - 15))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y - 15))
overLay(points: CGPoint(x: viewFrames.origin.x - 15, y: viewFrames.origin.y + viewFrames.height - 15))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height - 15))
overLay(points: CGPoint(x: viewFrames.origin.x - 15 , y: viewFrames.origin.y + viewFrames.height/2))
overLay(points: CGPoint(x: viewFrames.origin.x + viewFrames.width - 15, y: viewFrames.origin.y + viewFrames.height/2))
}
}
Upvotes: 3
Reputation: 297
I have created an enum with all the corners where the circle need to be placed.
enum Corners {
case topLeft
case topRight
case bottomLeft
case bottomRight
case centerLeft
case centerRight
}
I am adding the a circular view programmatically to the viewcontroller's view and setting it's color. Here, I have given white, you can change it to your respective transparent background.
func addCircularViews(toCorners corners: [Corners]) {
for corner in corners {
let circleView = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
circleView.layer.cornerRadius = circleView.frame.width/2
circleView.backgroundColor = UIColor.white
self.view.addSubview(circleView)
setPosition(forCircularView: corner, circleView)
}
}
I am setting the postion of the circle by changing the center of the circular view.
func setPosition(forCircularView corner: Corners,_ circleView: UIView) {
let screenFrame = UIScreen.main.bounds
switch corner {
case .topLeft:
circleView.center = CGPoint(x: screenFrame.origin.x, y: screenFrame.origin.y)
case .topRight:
circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width, y: screenFrame.origin.y)
case .bottomLeft:
circleView.center = CGPoint(x: screenFrame.origin.x , y: screenFrame.origin.y + screenFrame.height)
case .bottomRight:
circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width , y: screenFrame.origin.y + screenFrame.height)
case .centerLeft:
circleView.center = CGPoint(x: screenFrame.origin.x , y: screenFrame.origin.y + screenFrame.height/2)
case .centerRight:
circleView.center = CGPoint(x: screenFrame.origin.x + screenFrame.width , y: screenFrame.origin.y + screenFrame.height/2)
}
}
You can call the above function where ever required
addCircularViews(toCorners: [.topLeft, .topRight, .centerRight, .centerLeft, .bottomLeft, .bottomRight])
As the above is an array, the corners can be set according to requirement. Hope it helps!!
Upvotes: 0