Make a Simple Circular Button in SwiftUI

Published by malhal on

I came across this interesting Stack Overflow question How can I make a simple circular button in SwiftUI in macOS? It’s interesting because all of the proposed solutions required hard-coding a frame size. I decided to experiment with how to make a circle that dynamically resizes to the size of the text and came up with this:

Text("Click Me! Click Me! Click Me!")
    .allowsHitTesting(false) // allow taps exactly on the text to make it through to the button
    .padding()
    .background {
        Button {
            // button action
            print("Tapped")
        } label: {
                Circle()
                    .foregroundColor(.green)
                    .scaledToFill()
        }
        .contentShape(Circle()) // don't allow taps outside the circle
    }
Screenshot of a green circle containing black text

The idea is that first there is the text which determines the overall size of the button. Then there is a Button placed in the background that uses scaledToFill to expand beyond the bounds of the text. But since it is the button and not the text, the circle remains tappable. The contentShape modifier prevents tapping in the square bounds outwith the circle. The final trick is to allow taps that are exactly on the black text to pass through to activate the button.

I think it works ok, but haven’t tested it extensively, let me know if it works for you!

Categories: SwiftUI