iosswiftswiftuiscrollview

ScrollViewReader's scrollTo does not scroll


I have a simple SwiftUI list that I want to scroll to a row when a user click on a button. I have copied this code from hackingwithswift. It suppose to work, but it does not do.

struct ContentView: View {
    var body: some View {
        ScrollViewReader { proxy in
            VStack {
                Button("Jump to #50") {
                    proxy.scrollTo(5, anchor: .top)
                }

                List(0..<100) { i in
                    Text("Example \(i)")
                    .id(i)
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

I tested it on iOS 14.2 both on simulator and a physical device.

I read its documentation, but there is not much info. So how to scroll to a row, for example, row 50?


Solution

  • ScrollViewReader works only with either:

    It does not work with List of Range<Int> unless you set its id explicitly.

    Set id explicitly.

    // List(0..<100, id: \.self)
    
    struct ContentView: View {
        var body: some View {
            ScrollViewReader { proxy in
                VStack {
                    Button("Jump to #50") {
                        proxy.scrollTo(5, anchor: .top)
                    }
    
                    List(0..<100, id: \.self) { i in
                        Text("Example \(i)")
                        .id(i)
                    }
                }
            }
        }
    }
    
    // ForEach(0..<50000, id: \.self)
    
    struct ContentView: View {
        var body: some View {
            ScrollView {
                ScrollViewReader { proxy in
                    LazyVStack {
                        ForEach(0..<50000, id: \.self) { i in
                            Button("Jump to \(i+500)") {
                                proxy.scrollTo(i+500, anchor: .top)
                            }
                            Text("Example \(i)")
                                .id(i)
                        }
                    }
                }
            }
        }
    }