Reputation: 2825
I want to create a LazyHStack
without a ScrollView
so that I can use my own gestures etc.
What does having a ScrollView
do to a LazyVStack
so that only the visible elements have onAppear
called on them?
struct LazyTestView: View {
@State var nonScrollViewAppears = 0
@State var scrollViewAppears = 0
var body: some View {
VStack {
Text("Non-ScrollView - Views appeared: \(nonScrollViewAppears)")
ZStack {
LazyHStack(spacing:0) {
ForEach(0..<100, id: \.self) { index in
Rectangle().fill(.orange).frame(width: 100, height: 100)
.border(.black)
.overlay(Text("\(index)"))
.onAppear {
nonScrollViewAppears += 1
}
.onTapGesture {
print("tapped: \(index)")
}
}
}
.frame(width: 100, alignment: .leading)
.border(.red)
}
.frame(width: 150, height: 150)
.contentShape(Rectangle()) // Blocks hit testing
.clipped() // Clips the view
.border(.blue)
Divider()
Text("ScrollView - Views appeared: \(scrollViewAppears)")
ScrollView(.horizontal) {
LazyHStack(spacing:0) {
ForEach(0..<100, id: \.self) { index in
Rectangle().fill(.orange).frame(width: 100, height: 100)
.border(.black)
.overlay(Text("\(index)"))
.onAppear {
scrollViewAppears += 1
}
}
}
.frame(width: 100*100, height: 150, alignment: .leading)
.border(.red)
} // ScrollView
.frame(width: 150, height: 150)
.border(.blue)
}
}
}
I've added contentShape(Rectangle())
which blocks the hit testing and clipped()
which blocks the rendering of the elements outside the ZStack
. I've also tested this on a device.
I'm not sure why it's working like this.
Upvotes: 0
Views: 69