🤔

【SwiftUI】Drag した View がジャンプする件

2024/05/15に公開

問題点

ドラッグした円が中心にずれる。

struct TestDragGesture: View {
  @State private var location = CGPoint(x: 150, y: 150)

  var body: some View {
    Circle()
      .fill(.orange)
      .frame(width: 200)
      .position(location)
      .gesture(
        DragGesture()
          .onChanged { drag in
            location = drag.location
          }
      )
  }
}

円の中心とタップした位置のズレによるものですね!

ズレを考慮する

円の中心とタップした位置の ドラッグを開始した瞬間 のズレを取得します。

DragGesture() には、onStart() のような ドラッグを開始した瞬間 のコールバックメソッドはないようなので、Optional型 を使います。

ドラッグ完了のタイミングは、onEnded() で認識できます。

struct TestDragGesture: View {
  @State private var location = CGPoint(x: 150, y: 150)
  @State private var diff: CGPoint?

  var body: some View {
    Circle()
      .fill(.orange)
      .frame(width: 200)
      .position(location)
      .gesture(
        DragGesture()
          .onChanged { drag in
            if diff == nil {
              diff = CGPoint(
                x: location.x - drag.location.x,
                y: location.y - drag.location.y
              )
            }
            location.x = drag.location.x + diff!.x
            location.y = drag.location.y + diff!.y
          }
          .onEnded { _ in
            diff = nil
          }
      )
  }

これで意図通りです !

まとめ

そんな考え方で2つのコードでまとめておきます。どちらも単独で同じ挙動だと思います。

参考

https://twitter.com/maochanz/status/1790297337665056921
https://android.benigumo.com/20240514/drag-view/

Discussion