Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

ContentShape placement of button side effect for custom shape?

I would like to create a button out of my custom shapes, but it seems the contentShape is not taking effect when applied to the shape itself.

enter image description here

It only works when I add the modifier to the whole button. This seems contradictory to samples and wondering if there are side effects with this, or is there a more supported way to create buttons out of custom shapes?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

struct ContentView: View {
    let shape = Triangle()

    var body: some View {
        VStack {
            Button {
                print("Tapped: \(Date.now.timeIntervalSince1970)")
            } label: {
                shape
                    .stroke(Color.red, lineWidth: 10)
                    .frame(width: 200, height: 200)
                    //.contentShape(shape) <-- does not work!
            }
            .contentShape(shape) // <-- works but awkward
        }
        .padding(32)
    }
}

struct Triangle: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.move(to: CGPoint(x: rect.midX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
        return path
    }
}

>Solution :

I don’t see anything "awkward" here… by default button hit-test area is rectangular independently of Label (which is just presented label, button does not care about it).

If contentShape at that level confuses you, it is possible to create a modified styles and use it, like

            Button {

               // ... other code

            }
            .buttonStyle(TriangleButtonStyle())

// ...

struct TriangleButtonStyle: PrimitiveButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        Button(configuration)
            .contentShape(Triangle())
    }
}

or even make it generic on shape like TriangleButtonStyle<S: Shape> to allow any shape.

Tested with Xcode 13.4 / iOS 15.5

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading