SwiftUI: How to apply custom button styles

Martin Albrecht
2 min readApr 21, 2021
Photo by Anton Maksimov juvnsky on Unspla

To style a button with some predefined style inside your app you would usually use the buttonStyle method and apply one to it (e.g DefaultButtonStyle). In terms of accessibility it is most often recommended to stick with these button styles, but (as most developers probably know) in some cases the design dictates otherwise and you need more customization.

Creating and applying a view modifier could be an easy and quick solution to accomplish the desired effect, without the need of repeated code — but there is a more idiomatic way in swift programming by adopting a common protocol: ButtonStyle

👉 Conforming to common protocols is not only recommended by Apple, but also a good way to have structured and reusable code.

Another advantage of this approach is that it intrinsically avoids confusion. View modifiers are often very generic, which can lead to confusion if the desired modifier is really working with the intended view or not. Adopting to the ButtonStyle protocol solves this problem by strictly typing to the ButtonStyle protocol, which can only be passed to functions that support it.

Unfortunately, not all style protocols are easy to extend, or Apple just does not want us to do so, which can be quite frustrating, sometimes. The TextFieldStyle is a good example for such a protocol that cannot be extended the way described here — at least for now. We can only hope that this inconsistency is the result of a young and incomplete implementation of the framework itself and that it will change with future releases.

For our example we create a simple, rounded button with a gradient color background and some padding:

Custom Button Style

To keep things simple we don’t care about the logic inside the button and focus strictly on the layout part.

The protocol

The ButtonStyle protocol has one method requirement to conform to:

func makeBody(configuration: Self.Configuration) -> Self.Body

This method is the basic building block for the view. The configuration passed consists of the fields of our button (label and action), which you can modify inside. As said before, we don’t want to mess with the action itself and focus on the label field on which we apply all our desired modifiers:

The complete example

Instead of writing your own custom method for a view modifier and attach it you can now simply call the buttonStyle method with your custom style (line 24) every time you want to apply it to a button:

--

--