SwiftUIでは、先日紹介したDragGesture構造体から得られる情報を使って、ビューをドラッグアンドドロップで移動させる機能を簡単に実装することができる。

例として、まず座標空間(0, 0)でドラッグを開始し、(100, 150)までドラッグをおこなった場合、DragGesture.Valueのtranslationプロパティで得られる値は(100, 150)となる。

x軸の増加分は右方向、y軸の増加分は下方向へのドラッグを意味し、この時に得られるtranslationの値をもとにビューの位置を変更させる。

それではサンプルコードを紹介しながら具体的に解説していく。

struct ContentView: View {
  @State var position: CGSize = CGSize(width: 200, height: 200)
  
  var body: some View {
    VStack {
      Image("pasta")
        .resizable()
        .scaledToFit()
        .position(x: position.width, y: position.height)
        .gesture(
          DragGesture().onChanged { value in
            self.position = CGSize(
              width: value.startLocation.x + value.translation.width,
              height: value.startLocation.y + value.translation.height
            )
          }
          .onEnded { value in
            self.position = CGSize(
              width: value.startLocation.x + value.translation.width,
              height: value.startLocation.y + value.translation.height
            )
          }
      )
      Spacer()
      Text("x:\(position.width), y:\(position.height)")
    }
  }
}

まず、2行目でposition状態変数にビューの初期位置を設定しておく。

メインとなる処理は11行目のonChangedメソッド、17行目のonEndedメソッドに記述する。

それぞれのメソッドでは、DragGesture.Valueのプロパティを取得し、開始位置に移動距離を加算した値をposition状態変数に設定している。

ビューの位置はpositionモディファイアで指定しており、ドラッグで変化するposition状態変数の値に合わせてビューも移動することになる。