1

The code below presents a View in the middle of the screen, and allows you to drag that View. However, if you start the drag on the Button, the drag does not work. You need to drag on the area of the View around the Button.

Is there a way to make these two gestures know about each other, so that you can start the drag from anywhere in the View, even over the Button?

I'm imagining that putting a finger down on the Button would start both gestures as possibilities, and then if you would either lift up or start dragging to decide between the two.

struct ContentView: View {
    
    @State private var dragOffset: CGSize = .zero
    @State private var dragStartOffset: CGSize? = nil
    
    var body: some View {
        ZStack {
             Button("Hello") { print("hello") }
             .padding(30)
             .background(.regularMaterial)
             .gesture(dragGesture)
             .offset(dragOffset)
        }
    }
    
    private var dragGesture: some Gesture {
        DragGesture(minimumDistance: 0, coordinateSpace: .global)
            .onChanged { value in
                if dragStartOffset == nil {
                    dragStartOffset = dragOffset
                }
                dragOffset = dragStartOffset! + value.translation
            }
            .onEnded { _ in
                dragStartOffset = nil
            }
    }
}

func +(a: CGSize, b: CGSize) -> CGSize { CGSize(width: a.width + b.width, height: a.height + b.height) }

Rob N
  • 15,024
  • 17
  • 92
  • 165
  • 1
    Why button? Just use `TapGesture` on `Text("Hello")` and it will work with `DragGesture`. – Asperi Oct 21 '21 at 16:29
  • `Button` provides a lot of stuff beyond `Text`, but if that is the only way, I will do it. I just tried it with `Text` that there is still an extra delay on the drag if you start over the button (the `minimumDistance` is not zero). I'd still like to know if there is a way to control that. – Rob N Oct 21 '21 at 16:46

1 Answers1

2

Instead of .gesture(dragGesture) try .highPriorityGesture(dragGesture).

Scott McKenzie
  • 16,052
  • 8
  • 45
  • 70