SwiftUI DragGesture() get start location on screen
Asked Answered
T

1

5

I want to make a view "swipeable", however this view only covers a small share of the whole screen. Doing:

var body: some View {
    
    ZStack {
        Text("ABC")
            .gesture(DragGesture().onChanged(onChanged))
    }
}

func onChanged(value: DragGesture.Value) {
    print(value.startLocation)
    print("onChanged", value.location)
}

Gives me relative values where the user has swiped - however, without knowing the exact location of the view, I'm unable to know where the user's touch is on the screen.

In other words, when the Text is in the center of the screen, going all the way to the right edge gives 200px. But let's say the Text moved to the left, then it would be almost 400. I tried putting another gesture on the ZStack to save the initial value, however it appears you can't have multiple gestures within each other.

How can I make the listener translate the values so the left edge is 0 and the right edge is displayWidth in px, regardless of where the Text is?

Tati answered 8/10, 2021 at 19:39 Comment(2)
So you only want to start the gesture when dragging the Text, but get the global coordinates relative to the screen?Larhondalari
Hey George, that's it, exactly. The only other way I can think of is to use GeometryReader and compare coordinates for a DragGesture spanning over the whole screen but GeometryReader always messed up stuff and it sounds like a really hacky workaroundTati
L
10

You can make use of coordinate spaces, and use that with DragGesture.

Code:

struct ContentView: View {
    @State private var location: CGPoint = .zero

    var body: some View {
        VStack(spacing: 30) {
            Text("ABC")
                .background(Color.red)
                .gesture(
                    DragGesture(coordinateSpace: .named("screen")).onChanged(onChanged)
                )

            Text("Location: (\(location.x), \(location.y))")
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .coordinateSpace(name: "screen")
    }

    private func onChanged(value: DragGesture.Value) {
        location = value.location
    }
}
Larhondalari answered 8/10, 2021 at 20:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.