18
Jan
2022
Update SwiftUI Navigation Bar on Scroll
Reading time: 1 min
This recipe shows how to update navigation bar when the content underneath it scrolls.
The end result looks like this:
The recipe relies on the ObservableScrollView
from this recipe, because it can track its scroll offset. After that, it becomes trivial to check if the user has scrolled past a certain point and update the navigation bar.
The scrollToTop
functionality relies on a method from this recipe.
Here's the full code:
struct UpdateNavigationBarOnScroll: View {
@State var scrollOffset: CGFloat = .zero
@State var scrollToTop = false
private var hasScrolled: Bool {
scrollOffset > 0
}
var body: some View {
NavigationView {
scrollView
.navigationBarTitle(hasScrolled ? "Thanks!" : "Scroll, please!",
displayMode: .inline)
.navigationBarItems(trailing: navBarButton)
}
}
@ViewBuilder private var scrollView: some View {
ObservableScrollView(scrollOffset: $scrollOffset) { proxy in
LazyVStack {
ForEach(0..<100) { index in
Text("Row \(index)")
.id(index)
}
}
.onChange(of: scrollToTop) { newValue in
if newValue {
scrollToTop = false
withAnimation {
proxy.scrollTo(0, anchor: .top)
}
}
}
}
}
@ViewBuilder private var navBarButton: some View {
if hasScrolled {
Button("To top") {
scrollToTop = true
}
} else {
EmptyView()
}
}
}