---
title: Adding interactivity with gestures
framework: swiftui
role: article
role_heading: Article
path: swiftui/adding-interactivity-with-gestures
---

# Adding interactivity with gestures

Use gesture modifiers to add interactivity to your app.

## Overview

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. 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. Gesture modifiers offer three ways to receive updates: updating(_:body:), onChanged(_:), and onEnded(_:). Update transient UI state 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. 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 private 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 private var isDetectingLongPress = false     @State private 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. 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 private var isDetectingLongPress = false     @State private var totalNumberOfTaps = 0     @State private 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)         }     } }
