SwiftUI Button Tutorial: Customization
Learn how to easily customize your app buttons style with the minimum effort by leveraging the latest SwiftUI button modifiers. By Andy Pereira.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
SwiftUI Button Tutorial: Customization
20 mins
Buttons are critical in any app UI. In iOS development, UIKit provided structure for everything buttons-related, but since SwiftUI emerged, dealing with buttons is easier and more fun. SwiftUI introduced many modifiers since the first version in iOS 13 SDK, providing more capabilities and customization. It does the heavy lifting for developers and gives them more flexibility.
In this tutorial, you’ll implement a basic app with different SwiftUI button styles and shapes. Along the way, you’ll learn:
- The basics of SwiftUI buttons.
- How to take advantage of available shapes and sizes.
- What button roles are.
- How to make custom button styles.
- How to use menus and make custom menu styles.
Without further ado, let’s button it. :]
Getting Started
Download the materials for this tutorial — use the link at the top or bottom of this article.
Open the starter project in Xcode 13 — the files are placeholders for all the buttons’ types and styles you’ll be building. Build and run the app to render a beautiful SwiftUI List
.
Button Style Basics
Open KitchenSinkView.swift. Find borderedButtonView
. The three buttons have the same appearance. Change the appearance of the first button by adding the following modifier to the end of the button’s declaration:
.buttonStyle(.borderedProminent)
The button style borderedProminent
applies a standard prominent border artwork based on the button’s context. No matter your platform code’s platform, it’ll apply the proper styling to align with it. You needn’t worry about creating different buttons for each operating system — Apple is taking care of it.
Build and run. You’ll see how the first button style has changed.
In the same borderedButtonView
, add the buttonStyle
modifier to apply a new style to the remaining buttons in the section:
Button {
} label: {
Text("Bordered")
}
.buttonStyle(.bordered)
Button {
} label: {
Text("Borderless")
}
.buttonStyle(.borderless)
You just added the following two styles:
-
bordered
: LikeborderedProminent
, this style applies a lighter border artwork compared with the prominent border style around your button. -
borderless
: Though this style doesn’t have a visual effect, it still shows how you can force a button not to have a border. Because SwiftUI’s environment can apply styles to multiple buttons simultaneously, you’ll need to know how to keep a specific button borderless when other buttons aren’t.
Now that the buttons all have styles, let’s add color. These button styles can have tints applied and be rendered based on their style.
Still in borderedButtonView
, add the following modifier to the Section
container view level:
.tint(applyTint ? .mint : .primary)
Build and run. Toggle Apply Tint.
As you can see, each button knows what color to apply to the background and to the text. By using built-in styles, you make it possible to have sweet-looking buttons, all while maintaining a codebase that’s easy to update should the SwiftUI API change.
Button Roles
In iOS 15, Apple introduced button roles to SwiftUI, a value that allows you to describe a purpose for your button. Similar to styles, adding a role to the button will automatically apply a look and feel that’s distinct to the environment your app runs on.
Find buttonRolesView
. Replace these two buttons:
Button {
} label: {
Text("Destructive")
}
Button {
} label: {
Text("Cancel")
}
With the following code:
Button(role: .destructive) {
} label: {
Text("Destructive")
}
Button(role: .cancel) {
} label: {
Text("Cancel")
}
Here, you provided the following roles to each of the two buttons:
-
destructive
: This role indicates it will cause a “destructive” action to occur. Use this role to prompt for actions such as deleting items. -
cancel
: This role implies a cancel action. When paired with a destructive button, users have better visuals to help them make a decision.
When you use a List
, roles can also be applied as a swipe action. Replace the first button in buttonRolesView
with the following:
Button(role: .destructive) {
} label: {
Text("Destructive")
}
// 1
.swipeActions {
// 2
Button(role: .destructive) {
actionTaken = "Remove"
} label: {
Label("Remove", systemImage: "trash")
}
// 3
Button(role: .cancel) {
actionTaken = "Add"
} label: {
Label("Add", systemImage: "plus")
}
// 4
Button {
actionTaken = "Share"
} label: {
Label("Share", systemImage: "square.and.arrow.up")
}
.tint(.mint)
}
Here’s what you just added:
-
swipeActions
is a modifier you can add to a row in a list view. The buttons you provide in the closure will be present when the user swipes on the row. - A button that indicates something will be destroyed by selecting this action.
- A cancel button indicates the swipe action will “cancel” when selected.
- Finally, a basic button that has no role. You aren’t required to provide roles to buttons in swipe actions, so use them as necessary.
Build and run. Then swipe from right to left on the row labeled “Destructive.”
With the roles set on the first two buttons, see how Apple styles the “cancel” and “destructive” buttons, requiring almost no effort on your part.
All Shapes and Sizes
In addition to borders and styles, Apple also provides the ability to set shapes and sizes on buttons.
Shaping Up
Locate buttonShapesView
and replace the first button in the view with the following:
Button {
} label: {
Text("Rounded")
}
.buttonBorderShape(.roundedRectangle)
Just like setting a border style, setting the shape of your button can happen with a single modifier. Here, you’ve applied the style roundedRectangle
.
You’ll need to add one more modifier before the border can appear. Apply the following modifier to the Section
in buttonShapesView
:
.buttonStyle(.bordered)
That addition lets the buttons within the section know they should have a border applied.
Build and run. Notice how each button inside the section has a bordered style.
Notice how each of the buttons has the same border. Because you set the button style to the Section
, all buttons inside it inherit the same style.
You can apply custom shapes to a button. On the second button in buttonShapesView
, add the following modifier:
Button {
} label: {
Text("Custom Radius")
}
.buttonBorderShape(.roundedRectangle(radius: 12))
Here, you added a border shape that is a rectangle with a corner radius of 12 points.
Next, add the following modifier to the final button in buttonShapesView
:
Button {
} label: {
Text("Capsule")
}
.buttonBorderShape(.capsule)
Build and run. Each of these buttons has a border with a different shape.
You can customize any of your buttons with a few lines of code by combining borders and shapes.