I have a LazyVGrid like this.
struct ContentView: View {
private var columns: [GridItem] = [
GridItem(.adaptive(minimum: .infinity, maximum: .infinity), spacing: 0)
]
private var items = Array(stride(from: 0, to: 100, by: 1))
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
LazyVGrid(
columns: columns,
alignment: .center,
spacing: 10,
pinnedViews: []
) {
ForEach(0..<items.count, id: \.self) { i in
Text("\(i)")
.frame(width:UIScreen.main.bounds.width - 20, height:UIScreen.main.bounds.height - 150)
.background(Color.red)
.foregroundColor(.white)
.id(i)
}
}
}
}
}
.padding()
}
}
In this case, the grid shows just one cell per page (please run on iPhone 15 pro to see what I mean).
Is there a way to make a cell snap to the vertical center when the user releases the finger during scroll and the cell's top Y passed the center point (supposing the cell is being scrolled up) or the bottom Y passed the vertical center (supposing the cell is being scrolled down), like it was a page control?
iOS 17 Example
There are some nice to have goodies that they gave us with ScrollView in the latest iOS. Some of those being: scrollTargetLayout and scrollTargetBehavior:
var body: some View {
ScrollViewReader { proxy in
ScrollView {
VStack {
// LazyGrid - removed this to reduce confusion
}
.scrollTargetLayout() // <-- Here
}
.scrollTargetBehavior(.viewAligned(limitBehavior: .always)) // <-- Here
}
.padding()
}
In the example above, viewAligned
is limiting the behavior, which just means its scrolling one at a time.