Skip to content

Toolbar

Skip support for SwiftUI.View.toolbar on Android. Consult the SkipUI module for a complete list of supported SwiftUI.

The following example screens and source code is from SkipUI’s Showcase sample app ToolbarPlayground.swift

Android screenshot for Toolbar component (light mode) iPhone screenshot for Toolbar component (light mode) iPhone screenshot for Toolbar component (dark mode) Android screenshot for Toolbar component (dark mode)
import SwiftUI
enum ToolbarPlaygroundType: String, CaseIterable {
case `default`
case tint
case custom
case label
case toolbarItem
case toolbarItemGroup
case topLeadingItem
case topLeadingItemGroup
case topLeadingBackButtonHidden
case topLeadingTrailingItems
case bottom
case bottomGroup
case bottomSpaced
var title: String {
switch self {
case .default:
return "Default"
case .tint:
return "Tint"
case .custom:
return "Custom"
case .label:
return "Label"
case .toolbarItem:
return "ToolbarItem"
case .toolbarItemGroup:
return "ToolbarItemGroup"
case .topLeadingItem:
return ".topLeading"
case .topLeadingItemGroup:
return ".topLeading Group"
case .topLeadingBackButtonHidden:
return ".topLeading Back Hidden"
case .topLeadingTrailingItems:
return "Both Top"
case .bottom:
return "Bottom"
case .bottomGroup:
return "Bottom 3 Group"
case .bottomSpaced:
return "Bottom 3 Spaced"
}
}
}
struct ToolbarPlayground: View {
var body: some View {
List(ToolbarPlaygroundType.allCases, id: \.self) { type in
NavigationLink(type.title, value: type)
}
.toolbar {
PlaygroundSourceLink(file: "ToolbarPlayground.swift")
}
.navigationDestination(for: ToolbarPlaygroundType.self) {
switch $0 {
case .default:
DefaultToolbarItemPlayground()
.navigationTitle($0.title)
case .tint:
TintToolbarItemGroupPlayground()
.navigationTitle($0.title)
case .custom:
CustomToolbarItemPlayground()
.navigationTitle($0.title)
case .label:
LabelToolbarItemPlayground()
.navigationTitle($0.title)
case .toolbarItem:
ToolbarItemPlayground(placement: ToolbarItemPlacement.automatic, placement2: ToolbarItemPlacement.automatic)
.navigationTitle($0.title)
case .toolbarItemGroup:
ToolbarItemGroupPlayground(placement: ToolbarItemPlacement.automatic)
.navigationTitle($0.title)
case .topLeadingItem:
#if os(macOS) // ToolbarItemPlacement.topBarLeading unavailable on macOS
#else
ToolbarItemPlayground(placement: ToolbarItemPlacement.topBarLeading)
.navigationTitle($0.title)
#endif
case .topLeadingItemGroup:
#if os(macOS) // ToolbarItemPlacement.topBarLeading unavailable on macOS
#else
ToolbarItemGroupPlayground(placement: ToolbarItemPlacement.topBarLeading)
.navigationTitle($0.title)
#endif
case .topLeadingBackButtonHidden:
#if os(macOS) // ToolbarItemPlacement.topBarLeading unavailable on macOS
#else
ToolbarBackButtonHiddenPlayground()
.navigationTitle($0.title)
#endif
case .topLeadingTrailingItems:
#if os(macOS) // ToolbarItemPlacement.topBarLeading unavailable on macOS
#else
ToolbarItemPlayground(placement: ToolbarItemPlacement.topBarLeading, placement2: ToolbarItemPlacement.topBarTrailing)
.navigationTitle($0.title)
#endif
case .bottom:
#if os(macOS) // ToolbarItemPlacement.bottomBar unavailable on macOS
#else
ToolbarItemPlayground(placement: ToolbarItemPlacement.bottomBar, placement2: ToolbarItemPlacement.bottomBar)
.navigationTitle($0.title)
#endif
case .bottomGroup:
#if os(macOS) // ToolbarItemPlacement.bottomBar unavailable on macOS
#else
ToolbarBottomThreePlayground(spaced: false)
.navigationTitle($0.title)
#endif
case .bottomSpaced:
#if os(macOS) // ToolbarItemPlacement.bottomBar unavailable on macOS
#else
ToolbarBottomThreePlayground(spaced: true)
.navigationTitle($0.title)
#endif
}
}
}
}
struct DefaultToolbarItemPlayground: View {
@Environment(\.dismiss) var dismiss
@State var firstTapCount = 0
@State var secondTapCount = 0
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
Button("First: \(firstTapCount)") {
firstTapCount += 1
}
Button("Second: \(secondTapCount)") {
secondTapCount += 1
}
}
}
}
struct CustomToolbarItemPlayground: View {
@Environment(\.dismiss) var dismiss
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
Ellipse()
.fill(.red.gradient)
.frame(width: 100.0, height: 50.0)
.onTapGesture {
dismiss()
}
}
}
}
struct LabelToolbarItemPlayground: View {
@Environment(\.dismiss) var dismiss
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
Button(action: { dismiss() }) {
Label("Dismiss", systemImage: "trash")
}
}
}
}
struct TintToolbarItemGroupPlayground: View {
@Environment(\.dismiss) var dismiss
@State var firstTapCount = 0
@State var secondTapCount = 0
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
ToolbarItemGroup {
Button("First: \(firstTapCount)") {
firstTapCount += 1
}
.tint(.red)
Button("Second: \(secondTapCount)") {
secondTapCount += 1
}
.tint(.green)
}
}
}
}
struct ToolbarItemPlayground: View {
@Environment(\.dismiss) var dismiss
@State var firstTapCount = 0
@State var secondTapCount = 0
let placement: ToolbarItemPlacement
var placement2: ToolbarItemPlacement? = nil
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
ToolbarItem(placement: placement) {
Button("First: \(firstTapCount)") {
firstTapCount += 1
}
}
if let placement2 {
ToolbarItem(placement: placement2) {
Button("Second: \(secondTapCount)") {
secondTapCount += 1
}
}
}
}
}
}
struct ToolbarItemGroupPlayground: View {
@Environment(\.dismiss) var dismiss
@State var firstTapCount = 0
@State var secondTapCount = 0
let placement: ToolbarItemPlacement
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
ToolbarItemGroup(placement: placement) {
Button("First: \(firstTapCount)") {
firstTapCount += 1
}
Button("Second: \(secondTapCount)") {
secondTapCount += 1
}
}
}
}
}
struct ToolbarBottomThreePlayground: View {
@Environment(\.dismiss) var dismiss
@State var firstTapCount = 0
@State var secondTapCount = 0
@State var thirdTapCount = 0
let spaced: Bool
var body: some View {
List {
Button("Pop") {
dismiss()
}
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.toolbar {
#if os(macOS) // ToolbarItemPlacement.bottomBar unavailable on macOS
#else
ToolbarItemGroup(placement: .bottomBar) {
Button("First: \(firstTapCount)") {
firstTapCount += 1
}
if spaced {
Spacer()
}
Button("Second: \(secondTapCount)") {
secondTapCount += 1
}
if spaced {
Spacer()
}
Button("Third: \(thirdTapCount)") {
thirdTapCount += 1
}
}
#endif
}
}
}
struct ToolbarBackButtonHiddenPlayground: View {
@Environment(\.dismiss) var dismiss
var body: some View {
List {
ForEach(0..<100) { i in
Text("Content \(i)")
}
}
.navigationBarBackButtonHidden()
.toolbar {
#if os(macOS) // ToolbarItemPlacement.topBarLeading unavailable on macOS
#else
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") {
dismiss()
}
}
#endif
}
}
}