Search code examples
iosuser-interfaceswiftuiios-simulatortoolbar

How do I arrange SwiftUI Toolbar items?


I have a SwiftUI ToolBar with 4 buttons, however the code I implemented is not correct because the buttons end up in weird places when changing the device type in simulator.

Even worse, when viewed on iPhone 8 / 8 Plus, 2 of the buttons are on the far edges of the window.

How do I properly apply spacing/padding to ToolBar buttons so they are consistent across different iOS devices?

Thank you!

IPhone 8

 // This code spaces the buttons but they change positions depending on the iOS device


                 ToolbarItem {
                        HStack {
                            HStack {
                                ProfileUploadMediaButton()
                            }.padding([.trailing], 85)
                            HStack {
                                ProfileUsernameButton()
                            }.padding([.trailing], 84)
                            HStack {
                                ProfileLiveButton()
                            }.padding([.trailing], 6)
                            HStack {
                                AccountButton()
                            }.padding([.trailing], 12)
                        }
                    }
                })

IPhone Pro Max

// I was thinking code like this but all buttons are bunched together on the right-side of  // the screen...

                    ToolbarItem {
                        HStack {
                            ProfileUploadMediaButton()
                            ProfileUsernameButton()
                            ProfileLiveButton()
                            AccountButton()
                        }
                    }

Items are all bunched together


Solution

  • When you add ToolbarItems, there is an initializer where you can explicitly set the placement of each item. For your case, you would add 3 ToolbarItems, for the left, center, and right. I'd mention that the toolbar is meant to be dynamic, so it may look different on different devices on purpose.

    struct ToolbarView: View {
        
        var body: some View {
            NavigationView {
                VStack {
                    Text("Hello, world!")
                }
                .navigationTitle("Test")
                .toolbar(content: {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Image(systemName: "camera.fill")
                    }
                    ToolbarItem(placement: .principal) {
                        Text("Username")
                    }
                    ToolbarItem(placement: .navigationBarTrailing) {
                        HStack {
                            Image(systemName: "dot.radiowaves.left.and.right")
                            Image(systemName: "heart.fill")
                        }
                    }
                })
            }
        }
    
    }
    

    Per the documentation, here are the placement options. I'm guessing that when you don't explicitly add a placement, they default to .automatic.

    • automatic: The item is placed automatically, depending on many factors including the platform, size class, or presence of other items.

    • bottomBar: The item is placed in the bottom toolbar. Applies to iOS, iPadOS, and Mac Catalyst.

    • cancellationAction: The item represents a cancellation action for a modal interface.

    • confirmationAction: The item represents a confirmation action for a modal interface.

    • destructiveAction: The item represents a destructive action for a modal interface.

    • navigation: The item represents a navigation action.

    • navigationBarLeading: The item is placed in the leading edge of the navigation bar. Applies to iOS, iPadOS, tvOS, and Mac Catalyst.

    • navigationBarTrailing: The item is placed in the trailing edge of the navigation bar. Applies to iOS, iPadOS, tvOS, and Mac Catalyst.

    • primaryAction: The item represents a primary action.

    • principal: The item is placed in the principal item section.

    • ToolbarItemPlacement: The item represents a change in status for the current context.