Home > Mobile >  Using .gesture(LongPressGesture) break the Scrollview
Using .gesture(LongPressGesture) break the Scrollview

Time:02-28

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!

CodePudding user response:

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")
            }
    }
}
  • Related