0

I'm attempting to drag a view (the ZStack below) using the dragPiece gesture in the following code. If I have the .onChanged modifier commented out, this code works fine, in the sense that the view ends up repositioned. But when .onChanged is uncommented and active, the drag gesture seems to get stuck, repeatedly printing out the same width and height values, and the .onEnded modifier is never executed. This seems like it should be straightforward, so clearly I'm missing something. Any help will be appreciated.

struct PieceView: View {
    var id: String
    @State private var orientation: Int
    @State private var dragOffset = CGSize.zero
    @State var selected = false
    var dragPiece: some Gesture {
        DragGesture()
            .onChanged { value in
                dragOffset = value.translation
                print("width: \(dragOffset.width), height: \(dragOffset.height)")
            }
            .onEnded{ value in
                print("\(id) dragged")
                dragOffset = value.translation
                print("width: \(dragOffset.width), height: \(dragOffset.height)")
            }
    }
    var body: some View {
        ZStack {
            Image(id + "\(orientation)")
            Image("boardSquare")
                .padding(0)
                .gesture(dragPiece)
         }
        .offset(dragOffset)
    }
    init() {
        id = ""
        orientation = 0
    }
    init(id: String, orientation: Int = 0, gesture: String = "") {
        self.id = id
        self.orientation = orientation
    }
}
jayboh
  • 267
  • 3
  • 12
  • This should be helpful https://stackoverflow.com/a/59540581/12299030, and this https://stackoverflow.com/a/63693584/12299030. For more look SO by `DragGesture` - there are a lot of working examples. – Asperi Mar 18 '22 at 06:53
  • Thanks. I did look at many other examples of `DragGesture`, but I didn't find any examples where the same situation arose -- that is, where `onEnded` was never reached when `onChanged` was present. – jayboh Mar 18 '22 at 23:40

1 Answers1

0

It appears that .offset(dragOffset) must appear before .gesture(dragPiece). The following code works as expected:

struct PieceView: View {
    var id: String
    @State private var orientation: Int
    @State private var dragOffset = CGSize.zero
    @State var selected = false
    var dragPiece: some Gesture {
        DragGesture()
            .onChanged { value in
                dragOffset = value.translation
                print("width: \(dragOffset.width), height: \(dragOffset.height)")
            }
            .onEnded{ value in
                print("\(id) dragged")
                dragOffset = value.translation
                print("width: \(dragOffset.width), height: \(dragOffset.height)")
            }
    }
    var body: some View {
        ZStack {
            Image(id + "\(orientation)")
            Image("boardSquare")
                .padding(0)
                .offset(dragOffset)
                .gesture(dragPiece)
         }
    }
    init() {
        id = ""
        orientation = 0
    }
    init(id: String, orientation: Int = 0, gesture: String = "") {
        self.id = id
        self.orientation = orientation
    }
}

In my case, this leaves me with some other UI design issues, because I want the gesture to apply to Image("boardSquare") but the whole ZStack to be dragged. But that's a separate issue, and at least now I know what the problem was with my current code.

jayboh
  • 267
  • 3
  • 12