How to make a vertical ScrollView snap

139 views Asked by At

I have a vertical ScrollView in SwiftUI. I'm trying to make it snap. Horizontal snapping works just fine, but vertical doesn't. Im checking this in simulator and also on device.

struct ContentView: View {
    @State private var scrolledID: Int?
    @State private var items: [Int] = Array(0..<30)
    
    var body: some View {
        NavigationStack {
            VStack {
                if let scrolledID = scrolledID {
                    Text("scrolledID: \(scrolledID)")
                } else {
                    Text("scrolledID: none")
                }
                Text("count: \(items.count)")
                ScrollView(.vertical, showsIndicators: true) {
                    LazyVStack {
                        ForEach(items, id: \.self) { i in
                            RoundedRectangle(cornerRadius: 20)
                                .fill(Color.green)
                                .overlay {
                                    Text("Item \(i)")
                                }
                                .foregroundStyle(.white)
                                .containerRelativeFrame(.vertical,
                                                        count: 5,
                                                        span: 2,
                                                        spacing: 10,
                                                        alignment: .center)
                        }
                    }
                    .scrollTargetLayout()
                }
                .scrollTargetBehavior(.viewAligned) // .paging
                .safeAreaPadding([.vertical, .horizontal], 10)
                .scrollPosition(id: $scrolledID, anchor: .bottom)
                .toolbar {
                    Button("Scroll to first") {
                        scrolledID = items.first
                    }
                }
            }
        }
    }
}
1

There are 1 answers

1
Maq On

Top snapping works after replacing .scrollTargetBehavior(.viewAligned) with .scrollTargetBehavior(.viewAligned(limitBehavior: .always))