Issue #846
We use UIBezierPath
with addArc
to draw specific corner with different rounding values.
import SwiftUI
extension View {
func clipCorners(
topLeft: CGFloat = 0,
bottomLeft: CGFloat = 0,
topRight: CGFloat = 0,
bottomRight: CGFloat = 0
) -> some View {
clipShape(
SpecificCornerShape(
topLeft: topLeft,
bottomLeft: bottomLeft,
topRight: topRight,
bottomRight: bottomRight
)
)
}
}
struct SpecificCornerShape: Shape {
var topLeft: CGFloat = 0
var bottomLeft: CGFloat = 0
var topRight: CGFloat = 0
var bottomRight: CGFloat = 0
func path(in rect: CGRect) -> Path {
let minX = rect.minX
let minY = rect.minY
let maxX = rect.maxX
let maxY = rect.maxY
let path = UIBezierPath()
path.move(to: CGPoint(x: minX + topLeft, y: minY))
path.addLine(to: CGPoint(x: maxX - topRight, y: minY))
path.addArc(
withCenter: CGPoint(x: maxX - topRight, y: minY + topRight),
radius: topRight,
startAngle: CGFloat(3 * Double.pi / 2),
endAngle: 0,
clockwise: true
)
path.addLine(to: CGPoint(x: maxX, y: maxY - bottomRight))
path.addArc(
withCenter: CGPoint(x: maxX - bottomRight, y: maxY - bottomRight),
radius: bottomRight,
startAngle: 0,
endAngle: CGFloat(Double.pi / 2),
clockwise: true
)
path.addLine(to: CGPoint(x: minX + bottomLeft, y: maxY))
path.addArc(
withCenter: CGPoint(x: minX + bottomLeft, y: maxY - bottomLeft),
radius: bottomLeft,
startAngle: CGFloat(Double.pi / 2), endAngle: CGFloat(Double.pi), clockwise: true)
path.addLine(to: CGPoint(x: minX, y: minY + topLeft))
path.addArc(
withCenter: CGPoint(x: minX + topLeft, y: minY + topLeft),
radius: topLeft,
startAngle: CGFloat(Double.pi),
endAngle: CGFloat(3 * Double.pi / 2),
clockwise: true
)
path.close()
return Path(path.cgPath)
}
}
We can use this custom Shape
to draw custom border, since Shape has the stroke
method
struct BubbleModifier: ViewModifier {
func body(content: Content) -> some View {
content
.overlay(
SpecificCornerShape(
topLeft: 4,
bottomLeft: 4,
topRight: 8,
bottomRight: 8
)
.stroke(Asset.outline.color, lineWidth: 1)
)
}
}