SwiftUI ButtonStyle
A while ago, I created a button in SwiftUI. It's a simple button, but I want to be able to use this design in lots of places in my app. It has the app's theme colours, it has a particular font, it has a pill-shaped rounded appearance.
I initially created this as a View
, wrapping a Button with some customisations.
struct PurpleButton: View {
let buttonTitle: String
let action: () -> Void
var body: some View {
Button(buttonTitle, action: action)
.frame(maxWidth: .infinity)
.padding(EdgeInsets(top: 16, leading: 32, bottom: 16, trailing: 32))
.font(.system(.title3, design: .rounded))
.foregroundStyle(Color(.darkBackgroundText))
.background(Color(.primary))
.clipShape(Capsule())
}
}
This gives me a PurpleButtonView
, whose sole contents are a Button
, styled how I want. But SwiftUI has a better way.
By using a ButtonStyle, you can customise a Button
's appearance without wrapping it, avoiding creating that extra view in the view hierarchy.
struct PurpleButtonStyle: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(maxWidth: .infinity)
.padding(EdgeInsets(top: 16, leading: 32, bottom: 16, trailing: 32))
.font(.system(.title3, design: .rounded))
.foregroundStyle(Color(.darkBackgroundText))
.background(Color(.primary))
.clipShape(Capsule())
}
}
You can then create a Button
in the normal, simple way, and apply the style.
#Preview {
Button("Press Me") { print("Button pressed") }
.buttonStyle(PurpleButtonStyle())
}
You can clean this up a bit by creating an extension on ButtonStyle to define a static variable.
extension ButtonStyle where Self == PurpleButtonStyle {
static var purpleButton: Self {
PurpleButtonStyle()
}
}
#Preview {
Button("Press Me") { print("Button pressed") }
.buttonStyle(.purpleButton)
}
The extension works really well if you have a standard style but want to provide different customisations.
extension ButtonStyle where Self == PurpleButtonStyle {
static var purpleButton: Self {
PurpleButtonStyle(.standard)
}
static var secondaryPurpleButton: Self {
PurpleButtonStyle(.secondary)
}
static var cancelPurpleButton: Self {
PurpleButtonStyle(.cancel)
}
}
This pattern appears throughout SwiftUI. Styles are a great way to customise a component's appearance, often quite heavily, without having to wrap or try to subclass a core component.
Resources
That's quite a simple example for one button style. Here are some resources I found useful when learning about ButtonStyle
: