👋

【SwiftUI】.gestureについて

2024/10/20に公開

SwiftUI のジェスチャ操作についてです。
SwiftUI では、.gesture修飾子を使ってビューにジェスチャを追加することができます。

以下のコードでは、四角形ビューにタップジェスチャを追加しています。

Rectangle().foregroundColor(.red)
  .frame(width: 250, height: 350)
  .gesture( ここにジェスチャを定義する )

ジェスチャでは、3つのイベントハンドラがあります。

  • onEnded:イベントが終了した際に処理。
  • onChanged:ジェスチャの値が変わった際に処理。
  • updating:ジェスチャの値が変わるたびにジェスチャの状態を更新。

タップ

タップのジェスチャでは TapGestureを使用し、タップ終了時のイベントハンドラを定義します。

Rectangle().foregroundColor(.red)
  .frame(width: 250, height: 350).gesture(tapGesture)
  
var tapGesture: some Gesture {TapGesture()
  .onEnded {
   // タップ後の処理
  }
}

TapGesturecountパタメータを使用すると、指定した数の連続タップでジェクチャを起動することができます。

var tapGesture: some Gesture {TapGesture(count: 2) // 2回連続タップでジェスチャ起動
  .onEnded {
   // タップ後の処理
  }
}

連続タップにする場合は、2回が限度かなと思っています。
3回以上のタップだと使い勝手が悪くなってしまいますので、気をつけましょう。

長押し

長押しのジェスチャではLongPressGestureを使用します。

 Rectangle().foregroundColor(.red)
  .frame(width: 250, height: 350).gesture(longPressGesture)
 
var longPressGesture: some Gesture {LongPressGesture()
  .onEnded {
   // 長押し後の処理
  }
}

LongPressGestureminimumDurationパラメータの設定で、長押しの時間を指定することができます。
なにも指定しない場合は、デフォルトで 0.5 秒が設定されます。

var longPressGesture: some Gesture {LongPressGesture(minimumDuration: 1.0) { // 1秒後に動作
  .onEnded {
   // 長押し後の処理
  }}
}

ドラッグ

ドラッグのジェスチャではDragGestureを使用します。

var dragGesture: some Gesture {DragGesture() {
  .onChanged { value in
   // ドラッグ中の処理
  }

  .onEnded { value in
   // ドラッグ終了時の処理
  }}
}

以下のコードはオブジェクトをドラッグして移動させる処理です。

struct DragView: View {// 移動されるオブジェクトのサイズ@State private let circleSize: CGFloat = 100// オブジェクトの位置@State private var offset: CGSize = CGSize.zero 

 var dragGesture: some Gesture {
  DragGesture() {
   .onChanged { value in
    // 位置を更新
    offset = CGSize(width: value.startLocation.x + value.translation.width - circleSize/2,
            height: value.startLocation.y + value.translation.height - circleSize/2)
   }
  }}
 
 var body: some View {
  VStack {
   Spacer()
   Circle()
    .frame(width: circleSize, height: circleSize)
    .offset(offset)
    .gesture(dragGesture) // ドラッグジェスチャー
   Spacer()
  }}
}

以下の箇所で Circle オブジェクトの位置を更新させています。

offset = CGSize(width: value.startLocation.x + value.translation.width - circleSize/2,
            height: value.startLocation.y + value.translation.height - circleSize/2)
  • startLocation:ドラッグ開始位置を取得。
  • translation :ドラッグ開始位置から現在位置までの距離を取得。

まとめ

  • TapGesture: タップ
  • LongPressGesture: 長押し
  • DragGesture: ドラッグ

Discussion