I'm trying to create a bottom toolbar in SwiftUI where the background color fully expands to the edges of the screen, completely ignoring the safe areas. However, I keep running into issues where there's white space at the bottom or sides of the toolbar.
In my example below, the ignoresSafeArea(edges: .all)
doesn't seem to fully expand the black color to the bottom or sides. I've added a picture as a visual example as well:
Ideally, I'd like the black background of the toolbar to fully cover the bottom of the screen, ignoring the safe areas completely and dynamically adjust for different devices without introducing white spaces or disproportionate sizing.
How can I achieve this effect in SwiftUI? Any advice or improvements to my implementation would be greatly appreciated!
Example code:
import SwiftUI
// Primary view for app
struct ContentView: View {
var body: some View {
NavigationView {
GeometryReader { geometry in
let metrics = Metrics(geometry: geometry)
ZStack{
AppColors.background.ignoresSafeArea()
}
VStack(spacing: metrics.verticalSpacing * 2) {
VStack(spacing: metrics.verticalSpacing * 2) {
SpacesView()
.frame(height: metrics.tileSize)
LettersView()
.frame(height: metrics.tileSize)
}
.padding(.horizontal, metrics.horizontalPadding)
.padding(.top, metrics.verticalSpacing * 3)
VStack {
if gameFinished {
GameFinishedView()
} else {
CurrentScoreView()
}
}
.padding(.horizontal, metrics.horizontalPadding)
}
.padding(.vertical, metrics.verticalSpacing * 2)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
TopBar()
}
// Bottom tool bar integrated here
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
BottomBar()
}
}
}
}
}
}
// Bottom tool bar
struct BottomBar: View {
var body: some View {
GeometryReader { geometry in
ZStack {
// Black toolbar background to fully ignore safe areas
Color.black
.ignoresSafeArea(edges: .all)
// Toolbar content
HStack {
SubmitButton()
}
.padding(.horizontal, 16)
.padding(.vertical, 10)
}
.frame(width: geometry.size.width, height: geometry.size.height)
}
}
}
You should use toolbarBackground
to set the color of the tool bar.
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
BottomBar()
}
}
.toolbarBackgroundVisibility(.visible, for: .bottomBar)
.toolbarBackground(.black, for: .bottomBar)
Before iOS 18, toolbarBackgroundVisibility
is (confusingly) also called toolbarBackground
, so you'd write .toolbarBackground(.visible, for: .bottomBar)
.
This means that you don't need all that GeometryReader
, ZStack
, Color.black
, and other things in BottomBar
. BottomBar
can just be the three buttons - you don't even need an HStack
.
var body: some View {
YellowButton()
Spacer()
SubmitButton()
Spacer()
BlueButton()
}
If you are targeting versions older than iOS 16, consider using a safeAreaInset
instead of toolbar
.
GeometryReader { geo in
// ...
}
.safeAreaInset(edge: .bottom) {
BottomBar() // in this case BottomBar does need the Color.black and other things that makes it fill the whole width
}