Reputation: 1942
I have to create a tab with buttons and some custom border (Images below). Problem is I have to add cornerRadius
for each intersect but I'm not sure how to do it properly.
I have this code to draw tabs with border:
private func drawBorder(selectedTab: UIButton) {
// The Tab frame (below one)
guard let tabContainerFrame = vTabContainer?.frame else { return }
let borderColor = selectedTab.titleColor(for: .selected)
let tabFrame = selectedTab.convert(selectedTab.bounds, to: self)
let topMargin: CGFloat = 5
let tabOrigin = CGPoint(x: tabFrame.origin.x, y: tabFrame.origin.y - topMargin)
// Make paths to draw
let path = UIBezierPath()
path.move(to: tabOrigin) // Origin (top left)
path.addLine(to: CGPoint(x: tabFrame.maxX, y: tabOrigin.y)) // -> right
path.addLine(to: CGPoint(x: tabFrame.maxX, y: tabFrame.maxY)) // -> down
if tabFrame.maxX != tabContainerFrame.maxX {
path.addLine(to: CGPoint(x: tabContainerFrame.maxX, y: tabContainerFrame.origin.y)) // -> right
}
path.addLine(to: CGPoint(x: tabContainerFrame.maxX, y: tabContainerFrame.maxY)) // -> Down
path.addLine(to: CGPoint(x: tabContainerFrame.origin.x, y: tabContainerFrame.maxY)) // -> left
path.addLine(to: CGPoint(x: tabContainerFrame.origin.x, y: tabContainerFrame.origin.y)) // -> up
if tabOrigin.x != tabContainerFrame.origin.x {
path.addLine(to: CGPoint(x: tabOrigin.x, y: tabContainerFrame.origin.y)) // -> right
}
// Close the path. This will create the last line automatically.
path.close()
// Draw
let borderLayer = CAShapeLayer()
borderLayer.path = path.cgPath
borderLayer.lineCap = kCALineCapRound
borderLayer.lineJoin = kCALineJoinBevel
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = borderColor?.cgColor
borderLayer.cornerRadius = 10
borderLayer.lineWidth = 2
layer.addSublayer(borderLayer)
self.borderLayer = borderLayer
}
This is the result:
As you can see, even though I add cornerRadius = 10
, it just doesn't work. borderLayer.lineCap = kCALineCapRound
and borderLayer.lineJoin = kCALineJoinBevel
doesn't help also.
Bonus:
I'd like to have a way to implement dynamic @IBInspectable var lineCornerRadius: CGFloat = 10
.
Upvotes: 0
Views: 187
Reputation: 77462
If you are using UIBezierPath
to draw a shape, setting cornerRadius will have no effect on that path.
Instead, you want to use path.addCurve(to: ...)
to make your rounded corners.
For example:
pt1
is tabFrame's "left" and "top + 10" (your radius)pt2
is tabFrame's "left + 10" and "top"pt3
is the first curve's second "control point" - the top-left corner of tabFramept4
is tabFrame's "right - 10" and "top"pt5
is tabFrame's "right" and "top + 10"pt6
is the second curve's second "control point" - the top-right corner of tabFrameSo
path.addCurve(to: pt2, controlPoint1: pt1, controlPoint2: pt3)
adds a curve to pt2
... from pt1
... with curve control point of pt3
then:
path.addLine(to: pt4)
adds a line from the current point (pt2
) to pt4
then:
path.addCurve(to: pt5, controlPoint1: pt4, controlPoint2: pt6)
adds a curve to pt5
... from pt4
... with curve control point of pt6
The rest of your shape is normal line segments.
Upvotes: 3