scrollTo conflict with scrollTargetBehavior?

171 views Asked by At

I try to replicate the snapchat camera filters scroll in SwiftUI.

When I scroll manually it's working well thanks to new iOS 17 scroll API, it's centering on each circles. But on tap it's not working, scrollTo method don't keep the center of the circles, I tried many anchors but can't make it work for all circles. Sometimes it's work for the last circles but not the first ones.

Like you can see below, on the beginning of the gif I'm scrolling witg gesture (working), then I tap (not working anymore).

enter image description here

If I remove scrollTargetBehavior(.viewAligned) and scrollTargetLayout the scrollTo is working.

Here is a simplified code to reproduce the issue:


import SwiftUI

@main
struct scrollApp: App {
    var body: some Scene {
        WindowGroup {
            GeometryReader(content: { outerProxy in
                ScrollViewReader(content: { proxy in
                    ScrollView(.horizontal, showsIndicators: false) {
                        LazyHStack(spacing: 0) {
                            ForEach(0...10, id: \.self) { index in
                                Circle()
                                    .frame(width: 100, height: 100)
                                    .foregroundStyle(.primary)
                                    .id(index)
                                    .onTapGesture {
                                        print("tap \(index)")
                                        withAnimation {
                                            proxy.scrollTo(index, anchor: .center)
                                        }
                                    }
                            }
                        }
                        .padding(.horizontal, outerProxy.size.width * 0.5 - 100/2)
                        .scrollTargetLayout()
                    }
                    .scrollTargetBehavior(.viewAligned)
                    .overlay {
                        Circle()
                            .stroke(.red, lineWidth: 10)
                            .frame(width: 100, height: 100)
                    }
                })
            })
            
        }
    }
}

Only pure SwiftUI solutions will be validated, I already make it works on UIKit.

0

There are 0 answers