Reputation: 475
So I have the following struct and view extension to be able to add to any view, any ideas how to fix the corner of the view in the image below?
extension View {
func border(width: CGFloat, edges: [Edge], color: Color) -> some View {
overlay(EdgeBorder(width: width, edges: edges).foregroundColor(color))
}
}
struct EdgeBorder: Shape {
var width: CGFloat
var edges: [Edge]
func path(in rect: CGRect) -> Path {
var path = Path()
for edge in edges {
var x: CGFloat {
switch edge {
case .top, .bottom, .leading: return rect.minX
case .trailing: return rect.maxX - width
}
}
var y: CGFloat {
switch edge {
case .top, .leading, .trailing: return rect.minY
case .bottom: return rect.maxY - width
}
}
var w: CGFloat {
switch edge {
case .top, .bottom: return rect.width
case .leading, .trailing: return self.width
}
}
var h: CGFloat {
switch edge {
case .top, .bottom: return self.width
case .leading, .trailing: return rect.height
}
}
path.addPath(Path(CGRect(x: x, y: y, width: w, height: h)))
}
return path
}
}
I tried attaching it to a VStack as follows:
VStack {
// content
}
.clipShape(RoundedRectangle(cornerRadius: 20))
.border(width: 1, edges: [.leading, .bottom, .trailing], color: Color.black)
The only problem is that it ends up looking like this:
Upvotes: 4
Views: 591
Reputation: 4746
The problem is from your EdgeBorder
shape. It ONLY support borders without corners, it just adds one line for each edge to the final Path.
To resolve please try
Add one more param cornerRadius
when init the shape
Rework the algorithm to create Path
c - c
| |
c - c
Enable a corner only when 2 side exist.
var width: CGFloat
var edges: [Edge]
var cornerRadius: CGFloat
func path(in rect: CGRect) -> Path {
//1. build new rect
//2. build corners
let path = UIBezierPath(roundedRect: newRect, byRoundingCorners: corners, cornerRadii: CGSize(width: cornerRadius, height: cornerRadius))
return Path(path.cgPath)
}
Upvotes: 2
Reputation: 186
I round the borders like this with the view
layerMinY
O ----------- O
layerMinX | | layerMaxX
| |
O ----------- O
layerMaxY
self.myView.layer.borderWidth = 2
self.myView.layer.borderColor = UIColor.black.cgColor
self.myView.clipsToBounds = true
self.myView.layer.cornerRadius = 10
self.myView.layer.maskedCorners = [.layerMaxXMinYCorner,
.layerMaxXMaxYCorner]
Looks like this:
Upvotes: 3
Reputation: 188
As the comment said, clipping doesn't change the drawing path of the initial rectangle. Changing the border width to 0 should remove the outline rectangle.
Upvotes: 2