Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using .gesture(LongPressGesture) break the Scrollview

I'm using Swift 5, SwiftUI 3.0 on Xcode 13.2.

I have the following code:

  ZStack { ... custom button }
 .gesture(LongPressGesture(minimumDuration: 0.5, maximumDistance: 30)
        .onEnded { _ in
                withAnimation(.easeInOut(duration: 1.0)) {
                    // code when ended...
                }
        }
        .onChanged { _ in
            withAnimation(.easeInOut(duration: 0.2)) {
                // code when touched...
            }
            
        })

Let's call this CustomButton.

I then have this ScrollView and LazyVGrid:

ScrollView {
    VStack(spacing: 15) {
           let columns = Array(repeating: GridItem(.flexible(), spacing: 10), count: 1)

           LazyVGrid(columns: columns,spacing: 15) {
               CustomButton()
               CustomButton()
               // and then some more...
           }
    } 
}

Now when I remove the onChange handler from CustomButton, the scrolling works fine. So I am guessing, that since onChange() fires as soon as I tap the button, it takes precedence over the ScrollView. However, I need the animation that occurs after onChange() is fired, or after the user touches the button.

I've tried having an empty .onTapGesture {} before the .gesture() modifier. I've tried changing .gesture to .simulatenousGesture And I've tried most anything I can find on SO or the AppleDev forums.

I'm wondering if it's possible to have a button in a ScrollView, that:

  1. Accepts 0.0 minimumDuration touch, or .gesture().onChange
  2. Is still scrollable in ScrollView

Any help would be greatly appreciated, thank you!

like image 899
Meers E. Chahine Avatar asked Aug 09 '26 21:08

Meers E. Chahine


1 Answers

This variation works (don't ask me why...):

struct CustomButton: View {
    var body: some View {
        RoundedRectangle(cornerRadius: 15)
            .frame(height: 50)
        
            .onTapGesture {
                print("tapped")
            }
        
            .onLongPressGesture(minimumDuration: 0.5, maximumDistance: 30) {
                print("longpress ended")
            } onPressingChanged: { pressing in
                print("longpress changed")
            }
    }
}
like image 96
ChrisR Avatar answered Aug 12 '26 12:08

ChrisR



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!