Article

Adding Interactivity with Gestures 相互作用をジェスチャに加える

Use gesture modifiers to add interactivity to your app. ジェスチャ修飾子を使って相互作用機能をあなたのアプリに加えてください。

Overview 概要

Gesture modifiers handle all of the logic needed to process user-input events such as touches, and recognize when those events match a known gesture pattern, such as a long press or rotation. When recognizing a pattern, SwiftUI runs a callback you use to update the state of a view or perform an action. ジェスチャ修飾子は、さまざまなユーザ入力イベント、たとえばタッチなどに必要とされる論理の全てを取り扱います、そしてそれらのイベントが既知のジェスチャパターン、たとえば長押しや回転などに合致する場合に認識します。あるパターンを認識する時、SwiftUIは、ビューの状態を更新するまたはアクションを実行するためにあなたが使うコールバックを走らせます。

Add Gesture Modifiers to a View ジェスチャ修飾子をビューに加える

Each gesture you add applies to a specific view in the view hierarchy. あなたが加える各ジェスチャは、ビュー階層の中のある特定のビューに適用されます。 To recognize a gesture event on a particular view, create and configure the gesture, and then use the gesture(_:including:) modifier:


struct ShapeTapView: View {
    var body: some View {
        let tap = TapGesture()
            .onEnded { _ in
                print("View tapped!")
            }
        
        return Circle()
            .fill(Color.blue)
            .frame(width: 100, height: 100, alignment: .center)
            .gesture(tap)
    }
}

Respond to Gesture Callbacks ジェスチャコールバックに応答する

Depending on the callbacks you add to a gesture modifier, SwiftUI reports back to your code whenever the state of the gesture changes. あなたがジェスチャ修飾子へと加えるコールバックに依存して、SwiftUIはジェスチャの状態が変化する時はいつでもあなたのコードに報告します。 Gesture modifiers offer three ways to receive updates: updating(_:body:), onChanged(_:), and onEnded(_:).

Update Transient UI State 過渡UI状態を更新する

To update a view as a gesture changes, add a GestureState property to your view and update it in the updating(_:body:) callback. SwiftUI invokes the updating callback as soon as it recognizes the gesture and whenever the value of the gesture changes. For example, SwiftUI invokes the updating callback as soon as a magnification gesture begins and then again whenever the magnification value changes. SwiftUI doesn’t invoke the updating callback when the user ends or cancels a gesture. Instead, the gesture state property automatically resets its state back to its initial value. SwiftUIは、それがジェスチャを認識するとすぐにそしてジェスチュの値が変化する時はいつでも更新コールバックを発動します。例えば、SwiftUIは、拡大ジェスチャが開始するとすぐにそしてさらにまた拡大値が変化する時はいつでも更新コールバックを発動します。SwiftUIは、ユーザがジェスチャを終えるまたはとり消す時に、更新コールバックを発動しません。代わりに、ジェスチャ状態プロパティは、自動的にそれの状態をリセットしてそれの初期値に戻します。

For example, to make a view that changes color while the user performs a long press, add a gesture state property and update it in the updating callback.


struct CounterView: View {
    @GestureState var isDetectingLongPress = false
    
    var body: some View {
        let press = LongPressGesture(minimumDuration: 1)
            .updating($isDetectingLongPress) { currentState, gestureState, transaction in
                gestureState = currentState
            }
        
        return Circle()
            .fill(isDetectingLongPress ? Color.yellow : Color.green)
            .frame(width: 100, height: 100, alignment: .center)
            .gesture(press)
    }
}

Update Permanent State During a Gesture ジェスチャの間に永続する状態を更新する

To track changes to a gesture that shouldn’t reset once the gesture ends, use the onChanged(_:) callback. For example, to count the number of times your app recognizes a long press, add an onChanged(_:) callback and increment a counter.


struct CounterView: View {
    @GestureState var isDetectingLongPress = false
    @State var totalNumberOfTaps = 0
    
    var body: some View {
        let press = LongPressGesture(minimumDuration: 1)
            .updating($isDetectingLongPress) { currentState, gestureState, transaction in
                gestureState = currentState
            }.onChanged { _ in
                self.totalNumberOfTaps += 1
            }
        
        return VStack {
            Text("\(totalNumberOfTaps)")
                .font(.largeTitle)
            
            Circle()
                .fill(isDetectingLongPress ? Color.yellow : Color.green)
                .frame(width: 100, height: 100, alignment: .center)
                .gesture(press)
        }
    }
}

Update Permanent State When a Gesture Ends ジェスチャが終わる時に永続する状態を更新する

To recognize when a gesture successfully completes and to retrieve the gesture’s final value, use the onEnded(_:) function to update your app’s state in the callback. ジェスチャがうまく完了する時に認識するには、そしてジェスチャのもつ最終の値を回収するには、onEnded(_:)関数を使ってあなたのアプリのもつ状態をそのコールバックにおいて更新してください。 SwiftUI only invokes the onEnded(_:) callback when the gesture succeeds. For example, during a LongPressGesture if the user stops touching the view before minimumDuration seconds have elapsed or moves their finger more than maximumDistance points SwiftUI does not invoke the onEnded(_:) callback.

For example, to stop counting long press attempts after the user completes a long press, add an onEnded(_:) callback and conditionally apply the gesture modifier.


struct CounterView: View {
    @GestureState var isDetectingLongPress = false
    @State var totalNumberOfTaps = 0
    @State var doneCounting = false
    
    var body: some View {
        let press = LongPressGesture(minimumDuration: 1)
            .updating($isDetectingLongPress) { currentState, gestureState, transaction in
                gestureState = currentState
            }.onChanged { _ in
                self.totalNumberOfTaps += 1
            }
            .onEnded { _ in
                self.doneCounting = true
            }
        
        return VStack {
            Text("\(totalNumberOfTaps)")
                .font(.largeTitle)
            
            Circle()
                .fill(doneCounting ? Color.red : isDetectingLongPress ? Color.yellow : Color.green)
                .frame(width: 100, height: 100, alignment: .center)
                .gesture(doneCounting ? nil : press)
        }
    }
}

See Also 参照

Basic Gestures 基本ジェスチャ