Duck
Duck

Reputation: 35953

Need to clipShape with a Shape that has only top left and bottom left rounded corners

I have a view that I want to apply a clipShape modifier to a rounded rectangle that has only the top left and bottom left rounded corners.

I am using this extension to round specific corners of some views I have.

So, I would love if I could do this:

.clipShape(Rectangle().cornerRadius(20, [.topLeft, .topRight]))

But I got error saying Rectangle must be a shape...

So I suppose I have to create something like:

struct RectangleX: Shape { 
  func path(in rect: CGRect) -> Path {
    var radius = CGFloat.infinity
    var corners = UIRectCorner.allCorners
    let path = UIBezierPath(roundedRect: rect,
                            byRoundingCorners: corners,
                            cornerRadii: CGSize(width: radius,
                                                height: radius))
    return Path(path.cgPath)
  }
}

but I am failing to see how do I pass the rect to this.

Upvotes: 5

Views: 6935

Answers (1)

pawello2222
pawello2222

Reputation: 54496

Problem

The cornerRadius modifier already uses clipShape.

extension View {
    func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View {
        clipShape( RoundedCorner(radius: radius, corners: corners) )
    }
}

Which means that:

.clipShape(Rectangle().cornerRadius(20, [.topLeft, .topRight]))

can also be read as:

.clipShape(Rectangle().clipShape( RoundedCorner(radius: 20, corners: [.topLeft, .topRight]) ))

and you don't really need multiple clipShape modifiers.

Solution

Try the following instead (you don't need to use clipShape - the custom cornerRadius extension already calls it):

.cornerRadius(20, corners: [.topLeft, .topRight])

A more complete example:

struct ContentView: View {
    var body: some View {
        Rectangle()
            .fill(Color.red)
            .frame(width: 100, height: 100)
            .cornerRadius(20, corners: [.topLeft, .topRight])
    }
}

Alternatively, you can use clipShape explicitly:

.clipShape(RoundedCorner(radius: 20, corners: [.topLeft, .topRight]))

Upvotes: 4

Related Questions