I attached the View image. I want to achieve the small cut in bottom between the buy button and above flight information view.
-
use an png as background image from your designer, faster than draw code or add custom view – Quang Hà Sep 15 '21 at 06:27
2 Answers
I think the easiest way would be to create 2 circles as plain UIView
instances and set their center as the left and right edges of the parent view respectively.
Since you set clipsToBounds
to true
, they will be clipped and only half of them will be visible on the screen.
public class TestView: UIView {
private let leftCircle = UIView(frame: .zero)
private let rightCircle = UIView(frame: .zero)
public var circleY: CGFloat = 0
public var circleRadius: CGFloat = 0
public override init(frame: CGRect) {
super.init(frame: frame)
clipsToBounds = true
addSubview(leftCircle)
addSubview(rightCircle)
}
public override func layoutSubviews() {
super.layoutSubviews()
leftCircle.frame = CGRect(x: -circleRadius, y: circleY,
width: circleRadius * 2 , height: circleRadius * 2)
leftCircle.layer.masksToBounds = true
leftCircle.layer.cornerRadius = circleRadius
rightCircle.frame = CGRect(x: bounds.width - circleRadius, y: circleY,
width: circleRadius * 2 , height: circleRadius * 2)
rightCircle.layer.masksToBounds = true
rightCircle.layer.cornerRadius = circleRadius
}
}
I've created a sample project demonstrating that. Here is how it looks in my simulator (iPhone SE 11.2):

- 49,246
- 17
- 84
- 119
-
In tableViewCell, this is not working. The circle shows but not in center. override func layoutSubviews() { super.layoutSubviews() passView.circleY = passView.frame.height * 0.5 } – Ashu May 01 '20 at 06:55
-
In this way, we will not be able to add shadow to view, it will go over circles and will look odd, do you have any solution for this? – Emre Akcan Nov 03 '20 at 18:30
I had to do this with shadows. I tried creating a layer and subtracting another layer from it using evenOdd fillRule, however that didn't work since I need a specific path for shadows and evenOdd applies to the filling in the path instead.
In the end I just created the path manually
func setShadowPath() {
let path = UIBezierPath()
path.move(to: bounds.origin)
path.addLine(to: CGPoint(x: cutoutView.frame.minX, y: bounds.minY))
path.addArc(withCenter: CGPoint(x: cutoutView.frame.midX, y: bounds.minY),
radius: cutoutView.bounds.width/2, startAngle: .pi, endAngle: 0, clockwise: false)
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
path.addLine(to: CGPoint(x: bounds.minX, y: bounds.maxY))
path.close()
layer.shadowPath = path.cgPath
}
I created a "cutoutView" in my xib so I could trace around it easily.
That makes the shadow the correct shape, and then in order to create the cut itself I just created a layer using that same path
func setupBackground() {
let backgroundLayer = CAShapeLayer()
backgroundLayer.path = layer.shadowPath
backgroundLayer.fillColor = UIColor.white.cgColor
layer.insertSublayer(backgroundLayer, at: 0)
}

- 801
- 6
- 15