swiftuishapes

Custom RoundedRectangle Shape


I am working on a project with a custom roundedRectangle Shape that have a bump in one of its side, and from what i researched i have to draw a shape using custom path... however i wan't very successful in doing so, and i don't understand how to create it.

I would be grateful if someone help me create the shape in this attachment: Custom RoundedRectangle with a bump


Solution

  • To draw custom shapes with rounded corners, .addArc is your friend.

    struct LabelShape: Shape {
        let cornerRadius: CGFloat
        let tabWidth: CGFloat
            
        func path(in rect: CGRect) -> Path {
            var path = Path()
            path.move(to: CGPoint(x: cornerRadius, y: rect.height))
            path.addArc(tangent1End: CGPoint(x: rect.width, y: rect.height), tangent2End: CGPoint(x: rect.width, y: 0), radius: cornerRadius)
            path.addArc(tangent1End: CGPoint(x: rect.width, y: 0), tangent2End: CGPoint(x: 0, y: 0), radius: cornerRadius)
            path.addArc(tangent1End: CGPoint(x: rect.width - tabWidth, y: 0), tangent2End: CGPoint(x: rect.width - tabWidth, y: rect.height), radius: cornerRadius)
            path.addArc(tangent1End: CGPoint(x: rect.width - tabWidth, y: cornerRadius * 2), tangent2End: CGPoint(x: 0, y: cornerRadius * 2), radius: cornerRadius)
            path.addArc(tangent1End: CGPoint(x: 0, y: cornerRadius * 2), tangent2End: CGPoint(x: 0, y: rect.height), radius: cornerRadius)
            path.addArc(tangent1End: CGPoint(x: 0, y: rect.height), tangent2End: CGPoint(x: rect.width, y: rect.height), radius: cornerRadius)
            return path
        }
    }
    

    which you can use like this:

    struct ContentView: View {
        
        var body: some View {
            ZStack(alignment: .topTrailing) {
                LabelShape(cornerRadius: 10, tabWidth: 110)
                    .stroke(.red)
                    .frame(width: 300, height: 100)
                HStack(alignment: .firstTextBaseline, spacing: 4) {
                    Text("01:59:43")
                        .font(.system(size: 14, weight: .bold))
                    Text("Hours")
                        .font(.system(size: 10, weight: .regular))
                }
                .padding(4)
            }
        }
    }
    

    enter image description here

    For a great explanation on how this version of addArc works, see https://stackoverflow.com/a/71683201/123632