I want to create a LazyHStack
without a ScrollView
so I can use my own gestures etc.
What I’m wondering is what does having a ScrollView
do the a LazyVStack
to make it so 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 device.
Not sure why it’s working like this.