aheze
aheze

Reputation: 30534

SwiftUI - How to make ScrollView not bounce when content is smaller than bounds

I'm trying to make my ScrollView:

Here's my code:

struct ContentView: View {
    init() {
        UIScrollView.appearance().alwaysBounceVertical = false
    }
    var body: some View {
        ScrollView {
            Rectangle()
                .fill(Color.blue)
                .frame(height: 300) /// is smaller than the screen
                .padding()
        }
    }
}

I tried setting UIScrollView.appearance().alwaysBounceVertical = false, but the scroll view still bounces:

Swiping vertically on ScrollView, but still bounces

If I do UIScrollView.appearance().bounces = false, it stops bouncing. However, if I make the rectangle taller than the screen, it also stops bouncing (which I don't want).

Doesn't bounce (yay!) ... but doesn't bounce when the content overflows the screen
Swiping vertically on ScrollView with short rectangle doesn't bounce Swiping vertically on ScrollView with tall rectangle also doesn't bounce

How can I disable bouncing, but only when the content is smaller than scroll view's bounds?

Upvotes: 7

Views: 7876

Answers (3)

George
George

Reputation: 30481

For iOS 16.4+, see @JuvinR's answer


Well, when using SwiftUI-Introspect, setting alwaysBounceVertical to false actually works. I'm not exactly sure why setting the appearance as you did doesn't work though...

Anyway, here is some working example code:

struct ContentView: View {
    
    @State private var count = 5
    
    var body: some View {
        VStack {
            Picker("Count", selection: $count) {
                Text("5").tag(5)
                Text("100").tag(100)
            }
            .pickerStyle(SegmentedPickerStyle())
            
            ScrollView {
                VStack {
                    ForEach(1 ... count, id: \.self) { i in
                        Text("Item: \(i)")
                    }
                }
                .frame(maxWidth: .infinity)
            }
            .introspectScrollView { scrollView in
                scrollView.alwaysBounceVertical = false
            }
        }
    }
}

Result (unfortunately you can't see my mouse trying to drag the shorter list):

Result

Upvotes: 6

JuvinR
JuvinR

Reputation: 190

From iOS 16.4 onwards, there is a new modifier for called .scrollBounceBehavior that can be used to prevent ScrollView from bouncing when the content is smalled than the screen.

Example:

struct ContentView: View {
    
    var body: some View {
        ScrollView {
            Rectangle()
                .fill(Color.blue)
                .frame(height: 300)
                .padding()
        }
        .scrollBounceBehavior(.basedOnSize)
    }
    
}

Upvotes: 6

Morpheus
Morpheus

Reputation: 1319

Made a small extension based on George's answer using SwiftUI-Introspect:

extension View {
    func disableBouncingWhenNotScrollable() -> some View {
        introspectScrollView { scrollView in
            scrollView.alwaysBounceVertical = false
            scrollView.alwaysBounceHorizontal = false
        }
    }
}

Usage:

ScrollView {
    // content
}
.disableBouncingWhenNotScrollable()

Upvotes: 0

Related Questions