Radar: FB9697336 – ScrollViewReader scrollTo scrolls incorrectly sometimes, affected by unrelated padding

Hit this one while working on our video subtitles app Captionista once iOS 15 came out. Spooky scrolling action at a distance.

FB9697336 – ScrollViewReader scrollTo scrolls incorrectly sometimes, affected by unrelated padding

Please provide a descriptive title for your feedback:
ScrollViewReader scrollTo scrolls incorrectly sometimes, affected by unrelated padding

Which area are you seeing an issue with?
SwiftUI Framework

What type of feedback are you reporting?
Incorrect/Unexpected Behavior

Please describe the issue and what steps we can take to reproduce it:
Using the ScrollViewProxy.scrollTo function, you can get incorrect scrolling behaviour, seemingly dependent on padding applied to an ancestor of the view that is being scrolled.

Attached is a complete sample project (inline here is just the view source), and a video showing the problem.

The project should vertically scroll the tapped view to the center of the scroll view.

What actually happens is that sometimes it also scrolls horizontally, after the vertical scroll has completed.

If you remove the marked padding, it all works as expected. I’ve seen this on iOS 15 since the betas. It does not seem to happen on iOS 14 devices, even when built with Xcode 13.

The workaround is to apply the ancestor view padding to the view that is being scrolled.


import SwiftUI

struct ContentView: View {
    let items: [Int] = Array(0...50)
    var body: some View {
        VStack {
            Text("Keep tapping items to scroll them to center and it will drift to the side sometimes")

            GeometryReader { geometryProxy in
                ScrollViewReader { scrollProxy in
                    ScrollView(.vertical) {
                        VStack(spacing: 20) {
                            ForEach(items, id: \.self) { item in
                                Text("Item #\(item)")
                                .id(item)
                                .frame(height: 100)
                                .frame(width: 200)
                                .background(Color.green)
                                .onTapGesture {
                                    withAnimation {
                                        scrollProxy.scrollTo(item, anchor: .center)
                                    }
                                }
                                .contentShape(Rectangle())
                            }
                        }
                        .padding(.horizontal, 20) /// <<< This padding causes the bug
                        .frame(width: geometryProxy.size.width)
                    }
                }
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
}

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

Download Project

ScrollBug.zip

About

Marc Palmer (@marcpalmerdev) is a consultant and software engineer specialising in Apple platforms. He currently works on the iOS team of Concepts sketching app, as well as his own apps like video subtitle app Captionista. He created the Flint open source framework. He can also do a pretty good job of designing app products. Don't ask him to draw anything, because that's really embarrassing. You can find out more here.

Comments are closed.