Center view using ScrollTargetBehavior iOS 17

Hello!

I watched a great WWDC session that introduces new scroll view API in iOS 17: scrollTargetBehavior.

I'm developing a "carousel" view with new API, but got stuck with implementing a behaviour, when "inner" view, that is smaller than "edge" views, isn't centred while scrolling.

The first picture is how it works, the second one - is an expected result (so, the second card is centered when user scrolls).

Would appreciate any help or suggestions how to get it done.

PS: scrollTargetBehavior(.paging) didn't help much

~Paul

Attaching the source code:

import SwiftUI

struct CardView: View {
    
    private let name: String
    private let width: CGFloat

    init(id: String, width: CGFloat) {
        self.name = id
        self.width = width
    }
    
    var body: some View {
        Text("Card \(name)")
            .frame(width: width, height: 120)
            .background(Color.cyan)
            .clipShape(RoundedRectangle(cornerRadius: 12))
    }
}

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            let innderCardWidth = geometry.size.width * 0.7
            let edgeCardWidth = geometry.size.width * 0.9
            ScrollView(.horizontal) {
                LazyHStack {
                    CardView(id: "1", width: edgeCardWidth)
                    CardView(id: "2", width: innderCardWidth)
                    CardView(id: "3", width: edgeCardWidth)
                }
                .scrollTargetLayout()
            }
            .scrollTargetBehavior(.viewAligned)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
  • The interesting thing is that in an example that was mentioned during the session, author implemented the desired behaviour using new iOS 17 API, maybe I'm missing how HeroView was implemented?

Add a Comment

Replies

You can try giving your ScrollView the desired width (that of the cards), centering it horizontally, and using the .scrollClipDisabled() modifier on the ScrollView.