I have some code that works fine, but when I navigate back from DetailView, the toolbar appears cropped. Do you know how to fix it properly?
struct ContentView: View {
var body: some View {
NavigationView {
List {
Section {
ForEach(0..<10) { index in
NavigationLink(destination: DetailView()) {
Text("Row \(index+1)")
}
}
}
}
.scrollContentBackground(.hidden)
.background(Color.blue)
.toolbar {
multilineToolbar
}
}
}
var multilineToolbar: some ToolbarContent {
ToolbarItem(placement: .principal) {
VStack {
Text("Line 1")
.font(.largeTitle)
Text("Line 2")
.font(.title2)
}
}
}
}
The toolbar is not intended to be used for content with significant height and it may not be possible to increase the height of the space available.
As a workaround, you could show the header using .safeAreaInset(edge: .top)
instead. To emulate the behavior of the default toolbar, a material background can be added when the List
is scrolled.
With iOS 18, scrolling can be detected using onScrollGeometryChange
:
struct ContentView: View {
@State private var isScrolled = false
var body: some View {
NavigationStack {
List {
Section {
ForEach(0..<10) { index in
NavigationLink(destination: DetailView()) {
Text("Row \(index+1)")
}
}
}
}
.onScrollGeometryChange(for: Bool.self) { geometry in
geometry.contentOffset.y + geometry.contentInsets.top > 0
} action: { _, newVal in
isScrolled = newVal
}
.scrollContentBackground(.hidden)
.background(Color.blue)
.contentMargins(.top, 0)
.toolbarVisibility(.hidden, for: .navigationBar)
.safeAreaInset(edge: .top) {
multilineHeading
}
}
}
private var multilineHeading: some View {
VStack {
Text("Line 1")
.font(.largeTitle)
Text("Line 2")
.font(.title2)
}
.padding(.bottom, 6)
.frame(maxWidth: .infinity)
.background {
if isScrolled {
ZStack(alignment: .bottom) {
Rectangle()
.fill(.bar)
.ignoresSafeArea()
Divider()
}
}
}
.animation(.easeInOut(duration: 0.2), value: isScrolled)
}
}
You were using NavigationView
in your example. This should only be necessary if you still need to support iOS 15. In any case, if you need to support a version older than iOS 18, scrolling can be detected using a GeometryReader
behind the section header instead. The answer to Change NavigationStack title font, tint, and background in SwiftUI provides an example of this technique being used (it was my answer).