Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI ScrollView and OnLongPressGesture

When I press and hold on the Rectangle, I play a video. When the onLongPressGesture function is active, I cannot scroll through Rectangle. I can scroll through the space between two Rectangles. As if onLongPressGesture prioritizes itself. How can I run onLongPressGesture in ScrollView without any problems?

Code:

ScrollView(.horizontal) {
    HStack {
        ForEach(0 ..< 15) { item in
            RoundedRectangle(cornerRadius: 25.0)
                .frame(width: 125, height: 200)
                .padding(.horizontal)
                .onLongPressGesture {
                    self.videoStatus.isStartVideo = true
                }
        }
    }
}

enter image description here

like image 511
Ufuk Köşker Avatar asked Nov 28 '25 02:11

Ufuk Köşker


2 Answers

Use .onTapGesture { } before your .onLongPressGesture{ }

so, your code is going to like:

ScrollView(.horizontal) {
HStack {
    ForEach(0 ..< 15) { item in
        RoundedRectangle(cornerRadius: 25.0)
            .frame(width: 125, height: 200)
            .padding(.horizontal)
            .onTapGesture {  }
            .onLongPressGesture {
                self.videoStatus.isStartVideo = true
            }
    }
}
like image 197
Hexin Zhang Avatar answered Nov 30 '25 17:11

Hexin Zhang


You can create a UIViewRepresentable and attach a UILongPressGestureRecognizer to it:

struct GestureView: UIViewRepresentable {
    let callback: () -> Void

    func makeUIView(context: UIViewRepresentableContext<GestureView>) -> UIView {
        let view = UIView(frame: .zero)
        let gesture = UILongPressGestureRecognizer(target: context.coordinator, action: #selector(context.coordinator.action))
        gesture.delegate = context.coordinator
        gesture.cancelsTouchesInView = false
        view.addGestureRecognizer(gesture)
        return view
    }

    func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<GestureView>) {}

    class Coordinator: NSObject {
        let callback: () -> Void

        init(callback: @escaping () -> Void) {
            self.callback = callback
        }

        @objc func action(_ sender: UIPanGestureRecognizer) {
            if sender.state == .began {
                callback()
            }
        }
    }

    func makeCoordinator() -> GestureView.Coordinator {
        Coordinator(callback: callback)
    }
}

extension GestureView.Coordinator: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        true
    }
}

You can use this view for example as an overlay:

struct ContentView: View {
    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(0 ..< 15) { item in
                    RoundedRectangle(cornerRadius: 25.0)
                        .frame(width: 125, height: 200)
                        .padding(.horizontal)
                        .overlay(GestureView(callback: { print("callback") }))
                }
            }
        }
    }
}
like image 23
pawello2222 Avatar answered Nov 30 '25 17:11

pawello2222



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!