Search code examples
iosswiftuiscrollscrollview

Prevent SwiftUI scrollview scrolling when interacting with a specific component


I am trying to add a PKCanvasView to a scrollview with SwiftUI. But when I try to draw in the PKCanvasView it scrolls the scrollview instead.

In other words, how could I deactivate the scrolling when the user interacts with a specific view inside the scrollview?

I parsed through a lot of examples and blog articles and almost similar things but they were either too old or not for SwiftUI...

EDIT To give further details (and based on Guillermo answer), here is an additional sample:

struct ContentView: View {
    @State private var scrollDisabled = false

    var body: some View {
        VStack {
            ScrollView {
                VStack {

                    ForEach(1..<50) { i in

                        Rectangle()
                            .fill((i & 1 == 0) ? .blue: .yellow)
                            .frame(width: 300, height: 50)
                            .overlay {
                                Text("\(i)")
                            }
                    }
                }.frame(maxWidth: .infinity)
            }
            .scrollDisabled(scrollDisabled)
        }
        .frame(width: 300)
    }
}

Note that you cannot scroll touching the leading/trailing white borders. I'd like the same behavior for yellow items: if you try to move up/down while touching a blue cell it scrolls, but if you try the same with yellow the scrollview shouldn't scroll!

Sorry, I'm really trying my best to be clear... ^^


Solution

  • You can control how your elements respond to the drag gesture with the following:

    .gesture(DragGesture(minimumDistance:))
    

    For instance:

    struct ContentView: View {
        var body: some View {
            VStack {
                ScrollView {
                    VStack {
    
                        ForEach(1..<50) { i in
    
                            Rectangle()
                                .fill((i & 1 == 0) ? .blue: .yellow)
                                .frame(width: 300, height: 50)
                                .overlay {
                                    Text("\(i)")
                                }
                                .gesture(DragGesture(minimumDistance: i & 1 == 0 ? 100 : 0))
                        }
                    }.frame(maxWidth: .infinity)
                }
            }
            .frame(width: 300)
        }
    }
    

    will block the scrolling for the yellow elements!