I’m attempting to create a ScrollView with a LazyVStack the place two headers are pinned on the prime. It also needs to work inside a NavigationStack utilizing giant show mode for the title. Each headers ought to be contained in the ScrollView such that the animation for the massive title does work when scrolling (going from the massive title to the small one when scrolling down).
That is what I attempted:
struct StickyHeaderHeightKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func cut back(worth: inout CGFloat, nextValue: () -> CGFloat) {
worth = nextValue()
}
}
struct ContentView: View {
let scrollCoordinateSpace = "scroll"
@State non-public var headerHeight: CGFloat = 0
var physique: some View {
NavigationStack {
ScrollView {
VStack(alignment: .main, spacing: 0) {
GeometryReader { geometry in
let body = geometry.body(in: .named(scrollCoordinateSpace))
let offset = max(0, -frame.minY)
HStack {
Picture(systemName: "pin.fill")
Textual content("Sticky Header")
.font(.headline)
Spacer()
}
.padding()
.background(Colour.crimson.opacity(0.8))
.offset(y: offset)
.background(
GeometryReader { proxy in
Colour.clear
.desire(key: StickyHeaderHeightKey.self, worth: proxy.dimension.top)
}
)
}
.body(top: headerHeight)
.zIndex(1)
// --- Fundamental Content material ---
LazyVStack(spacing: 0, pinnedViews: .sectionHeaders) {
ForEach(0..<50) { index in
Part {
VStack(alignment: .main, spacing: 0) {
Textual content("Content material (index + 1)")
.padding(.vertical, 10)
.padding(.horizontal)
Textual content("Content material (index + 1)")
.padding(.vertical, 10)
.padding(.horizontal)
Textual content("Content material (index + 1)")
.padding(.vertical, 10)
.padding(.horizontal)
}
.background(Colour.inexperienced.opacity(0.5))
} header: {
VStack(spacing: 0) {
Textual content("Header")
.padding(.vertical, 6)
.padding(.horizontal)
.background(Colour.blue.opacity(0.5))
}
.body(maxWidth: .infinity, alignment: .main)
.background(Colour.blue.opacity(0.5))
}
}
}
}
}
.coordinateSpace(identify: scrollCoordinateSpace)
.navigationTitle("Massive Title")
.navigationBarTitleDisplayMode(.giant)
.onPreferenceChange(StickyHeaderHeightKey.self) { worth in
headerHeight = worth
}
}
}
}
The issue I’m dealing with is that the headers from the LazyVStack Part are at all times pinned on the prime most place of the ScrollView and never under the crimson sticky header.