I have a LazyVStack
inside a ScrollView
that sits below a smaller view (the yellow view in the image).
The problem is that when the grid is scrolled up, the cells can still receive taps through the yellow view which I really don't want. I want to put a search TextField
into that view and the touches get mixed up and the user experience is a mess. In the example code I added a button to swap to a List
to check if that had the same scrolling problem. It doesn't.
import SwiftUI
struct ContentView: View {
@State private var useList = false
@State private var gridLayout: [GridItem] = [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]
var data = (0...249).map { "\($0)" }
var body: some View {
NavigationView {
VStack {
TopInfoPane()
if useList {
List(data, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Text(item)
}
}
} else {
ScrollView {
LazyVGrid(columns: gridLayout, alignment: .center, spacing: 8) {
ForEach(data, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Cell(item: item)
}
}
}
}
}
}.navigationBarTitle("Scroller")
.navigationBarItems(trailing: Button(action: { useList.toggle() }) { Text("Swap") })
}
}
}
struct Cell: View {
var item: String
var body: some View {
Text(item)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 75)
.background(Color.green)
}
}
struct TopInfoPane: View {
var body: some View {
Text("TopInfoPane")
.frame(height: 48)
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.yellow)
}
}
I've tried setting animation on the view to nil and setting .allowsHitTesting(false
) but they didn't help. I'm at a loss because I really didn't expect the ScrollView
to scroll beyond its own frame anyway.
Try to clip ScrollView as follows
ScrollView {
LazyVGrid(columns: gridLayout, alignment: .center, spacing: 8) {
ForEach(data, id: \.self) { item in
NavigationLink(destination: Text(item)) {
Cell(item: item)
}
}
}
}
.contentShape(Rectangle())
.clipped()