Updated for Xcode 14.2
SwiftUI’s toolbar allows the user to customize any toolbar items we allow, and it takes five small steps:
.secondaryAction
category.The “unique, stable” identifier requirement matters, because this is what SwiftUI uses to remember the user’s settings – “toolbar X has button A, then C, then F.”
Note: Only some platforms support toolbar customization. This API will work best on iPadOS and macOS, where complicated toolbars are more common.
Here’s a code sample showing all those steps:
NavigationStack {
Text("SwiftUI")
.navigationTitle("Welcome")
.toolbar(id: "options") {
// this is a primary action, so will always be visible
ToolbarItem(id: "settings", placement: .primaryAction) {
Button("Settings") { }
}
// this is a standard secondary action, so will be customizable
ToolbarItem(id: "help", placement: .secondaryAction) {
Button("Help") { }
}
// another customizable button
ToolbarItem(id: "email", placement: .secondaryAction) {
Button("Email Me") { }
}
// a third customizable button, but this one won't be in the toolbar by default
ToolbarItem(id: "credits", placement: .secondaryAction, showsByDefault: false) {
Button("Credits") { }
}
}
.toolbarRole(.editor)
}
Download this as an Xcode project
When you run that code, you’ll see a details button on the trailing edge of your toolbar – tapping that will show a Customize Toolbar menu that enables customization.
By default this will make all the secondary action buttons individually customizable, but if you wrap two or more buttons in a ControlGroup
they become attached for customization purposes – the user must add both or neither. ControlGroup
is great for things like font adjustments, like this:
NavigationStack {
Text("SwiftUI")
.navigationTitle("Welcome")
.toolbar(id: "font") {
ToolbarItem(id: "font", placement: .secondaryAction) {
ControlGroup {
Button {
// decrease font
} label: {
Label("Decrease font size", systemImage: "textformat.size.smaller")
}
Button {
// increase font
} label: {
Label("Increase font size", systemImage: "textformat.size.larger")
}
} label: {
Label("Font Size", systemImage: "textformat.size")
}
}
}
.toolbarRole(.editor)
}
Download this as an Xcode project
Tip: If you don’t add a label for your ControlGroup
, SwiftUI will use the labels for the buttons it contains.
SPONSORED Build a functional Twitter clone using APIs and SwiftUI with Stream's 7-part tutorial series. In just four days, learn how to create your own Twitter using Stream Chat, Algolia, 100ms, Mux, and RevenueCat.
Sponsor Hacking with Swift and reach the world's largest Swift community!
Link copied to your pasteboard.