Skip to main content

How to make a ScrollView snap with paging or between child views

About 2 minSwiftSwiftUIArticle(s)bloghackingwithswift.comcrashcourseswiftswiftuixcodeappstore

How to make a ScrollView snap with paging or between child views 관련

SwiftUI by Example

Back to Home

How to make a ScrollView snap with paging or between child views | SwiftUI by Example

How to make a ScrollView snap with paging or between child views

Updated for Xcode 15

New in iOS 17

SwiftUI's ScrollView moves smoothly by default, but with the scrollTargetLayout() and scrollTargetBehavior() modifiers we can make it automatically snap to either to specific child views or to whole pages.

As an example, this places 10 rounded rectangles in a horizontal scroll view, with each one being a scroll target. Because .scrollTargetBehavior() is set to .viewAligned, SwiftUI will automatically snap between each of the rounded rectangles.

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            LazyHStack {
                ForEach(0..<10) { i in
                    RoundedRectangle(cornerRadius: 25)
                        .fill(Color(hue: Double(i) / 10, saturation: 1, brightness: 1).gradient)
                        .frame(width: 300, height: 100)
                }
            }
            .scrollTargetLayout()
        }
        .scrollTargetBehavior(.viewAligned)
        .safeAreaPadding(.horizontal, 40)
    }
}

Download this as an Xcode projectopen in new window

Coloured shapes scrolling horizontally, with each scroll swipe snapping to a view.
Coloured shapes scrolling horizontally, with each scroll swipe snapping to a view.

That uses scrollTargetLayout() to make everything inside the layout be a scroll target. If you only want some child views to be snapped to, you should remove that and instead attach scrollTarget() to individual views.

An alternative scroll targeting behavior is .paging, which makes the ScrollView move by exactly one screen width or height depending on your scroll direction:

ScrollView {
    ForEach(0..<50) { i in
        Text("Item \(i)")
            .font(.largeTitle)
            .frame(maxWidth: .infinity)
            .frame(height: 200)
            .background(.blue)
            .foregroundStyle(.white)
            .clipShape(.rect(cornerRadius: 20))
    }
}
.scrollTargetBehavior(.paging)

Download this as an Xcode projectopen in new window

Text scrolling vertically, with each scroll swipe moving one page at a time.
Text scrolling vertically, with each scroll swipe moving one page at a time.
Similar solutions…
How to make a ScrollView start at the bottom | SwiftUI by Example

How to make a ScrollView start at the bottom
How to flash the scroll bar indicators of a ScrollView or List | SwiftUI by Example

How to flash the scroll bar indicators of a ScrollView or List
How to disable ScrollView clipping so contents overflow | SwiftUI by Example

How to disable ScrollView clipping so contents overflow
How to add horizontal and vertical scrolling using ScrollView | SwiftUI by Example

How to add horizontal and vertical scrolling using ScrollView
How to indent the content or scroll indicators in a ScrollView | SwiftUI by Example

How to indent the content or scroll indicators in a ScrollView

이찬희 (MarkiiimarK)
Never Stop Learning.