11.9 C
New York
Sunday, April 6, 2025

ios – A number of pinned views on the prime of a LazyVStack inside a ScrollView


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.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles