LazyVGrid inside ScrollView not pinning section header

If I place a LazyVGrid inside a ScrollView with other views inside another ScrollView. The pinnedViews option of the LazyVGrid stops working. The section header scrolls out of the viewport like it's not pinned.

The complete view should scroll horizontally without another horizontal scrolling on the grid. The grid itself is wider than than the device width so it should scroll horizontally. The problem is now that the pinnedViews option of the LazyVGrid is not working.

If I remove the inner ScrollView and set the scroll mode of the outer to [.vertical, .horizontal] the pinned header works, except that now the view above and below the grid are also the same width of the LazyVGrid, which is not wat I want.

Is it possible to pin the section header to the outer ScrollView and not to the direct parent ScrollView of the LazyVGrid?

struct ContentView: View {
    var body: some View {
        ScrollView(.vertical) {
            Text("Other content")
                .frame(maxWidth: .infinity, minHeight: 100)
                .background(Color.yellow)

            ScrollView(.horizontal) {
                LazyVGrid(
                    columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9),
                    spacing: 16,
                    pinnedViews: [.sectionHeaders]
                ) {
                    Section(header: header) {
                        ForEach(1..<500) {
                            Text("Cell #\($0)")
                        }
                    }
                }
            }

            Text("Other content")
                .frame(maxWidth: .infinity, minHeight: 100)
                .background(Color.yellow)
        }
    }

    var header: some View {
        LazyVGrid(
            columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9),
            spacing: 16
        ) {
            ForEach(1..<10) {
                Text("Header \($0)")
            }
        }
        .padding(.vertical)
        .background(Color.blue)
        .foregroundColor(.white)
    }
}

The example is complete so you can test it easily. It works as expected, except that the pinned section header is not working.

See if this meets your expectations

Changes:

  • The outer most is a horizontal scroll view
  • Inside that you have a vertical scroll view
  • Move the other content inside the vertical scroll view
    var body: some View {
        ScrollView(.horizontal) {
            ScrollView(.vertical) {
                Text("Other content")
                    .frame(maxWidth: .infinity, minHeight: 100)
                    .background(Color.yellow)

                LazyVGrid(
                    columns: Array(repeating: GridItem(.fixed(200), spacing: 0, alignment: .center), count: 9),
                    spacing: 16,
                    pinnedViews: [.sectionHeaders]
                ) {
                    Section(header: header) {
                        ForEach(1..<500) {
                            Text("Cell #\($0)")
                        }
                    }
                }

                Text("Other content")
                    .frame(maxWidth: .infinity, minHeight: 100)
                    .background(Color.yellow)
            }
        }
    }
LazyVGrid inside ScrollView not pinning section header
 
 
Q