> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/swiftui/gestures/long-press.md).

# Long Press

[SwiftUI](/ios/swiftui.md) ⟩ [Gestures](/ios/swiftui/gestures.md) ⟩ Long Press

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="warning" %}
⭐️ <mark style="color:purple;">`.onEnded()`</mark>

* 只有時間按超過 <mark style="color:blue;">`minimumDuration`</mark> 才會觸發❗️
* if the user <mark style="color:orange;">**stops touching**</mark> the view before [`minimumDuration`](https://developer.apple.com/documentation/swiftui/longpressgesture/minimumduration) seconds have elapsed or <mark style="color:orange;">**moves their finger**</mark> more than [`maximumDistance`](https://developer.apple.com/documentation/swiftui/longpressgesture/maximumdistance) points SwiftUI <mark style="color:red;">**does not invoke**</mark> the [`onEnded(_:)`](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\)) callback.
  {% endhint %}

{% hint style="success" %}
⭐️ <mark style="color:purple;">`.onChanged()`</mark>

* <mark style="color:red;">**只要摸到，就會觸發**</mark>，但「<mark style="color:red;">**只觸發一次**</mark>」，就算摸再久，也只觸發一次，不會連續觸發，附送的 `value` 總是 `true`。但「<mark style="color:red;">**每摸一次，就觸發一次**</mark>」。
  {% endhint %}
  {% endtab %}

{% tab title="💾 程式" %}
{% embed url="<https://youtu.be/l3sAOL4_X2Q>" %}

📗 參考：[Mastering SwiftUI](https://www.appcoda.com/swiftui/), Ch. 17: Using Gestures (p.371)

```swift
import SwiftUI

struct ContentView: View {
    
    // star image size state (true: small, false: big)
    @State private var isSmallStar = false
    
    // ⭐️ `@GestureState` tracks the state change of a gesture
    //    `isStarPressed` indicates whether a tap event is detected
    @GestureState private var isStarPressed = false
    
    var body: some View {
        Image(systemName: "star.circle.fill") 
            .font(.system(size: 200))
            // ⭐️ dimmer when star is pressed
            .opacity(isStarPressed ? 0.4 : 1)
            .scaleEffect(isSmallStar ? 0.5 : 1.0) 
            .animation(.easeInOut) 
            .foregroundColor(.yellow)
            .overlay(
                Text(verbatim: "\(isStarPressed)")
                    .foregroundColor(isStarPressed ? .pink : .secondary)
            )
            .gesture(
                LongPressGesture(minimumDuration: 1.0)
                    // on pressed: (tap and hold)
                    // ⭐️ update `@GestureState` var as the gesture's value changes.
                    // • value: LongPressGesture.Value == Bool (current value)
                    //   gesture's current value (`true` indicates a tap is detected)
                    // • state: inout State == Bool (previous gesture's value)
                    //   `state` == `isStarPressed` in this case
                    // • transaction:
                    //   stores the "context"(?) of the gesture.
                    .updating($isStarPressed) { (value, state, _) in 
                        // ⭐️ save current value (is pressed or not?)
                        state = value
                    }
                    // on long pressed:
                    // • value: LongPressGesture.Value == Bool (gesture's final value)
                    // 🔸 註：
                    //    只有時間超過 `minimumDuration` 才會引發 onEnded❗️ 
                    //    而且 `isStarPressed` 會馬上變為 false❗️ 
                    .onEnded { _ in
                        // ⭐️ toggle image size when long pressed
                        isSmallStar.toggle()
                    }
            )
    }
}
```

{% endtab %}

{% tab title="💈範例" %}

* [long press + drag](/ios/swiftui/gestures/combine/sequenced/longpressdrag.md)
  {% endtab %}

{% tab title="📗 參考" %}

* Design+Code ⟩ [SwiftUI Long Press Gesture and Tap Progress Animation](https://youtu.be/fuTDDeKs_gc)
  {% endtab %}

{% tab title="📘 手冊" %}

* [SwiftUI](https://developer.apple.com/documentation/swiftui) ⟩&#x20;
  * [Gestures](https://developer.apple.com/documentation/swiftui/gestures) ⟩&#x20;
    * [Gesture](https://developer.apple.com/documentation/swiftui/gesture) (<mark style="color:orange;">**protocol**</mark>)
      * [.updating(\_:body:)](https://developer.apple.com/documentation/swiftui/gesture/updating\(_:body:\))
      * [.onChanged(\_:)](https://developer.apple.com/documentation/swiftui/gesture/onchanged\(_:\))
      * [.onEnded(\_:)](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\))
    * [LongPressGesture](https://developer.apple.com/documentation/swiftui/longpressgesture) (<mark style="color:red;">**struct**</mark>)
  * [View](https://developer.apple.com/documentation/swiftui/view) ⟩ [Input and Event Modifiers](https://developer.apple.com/documentation/swiftui/view-input-and-events) ⟩&#x20;
    * [.gesture(\_:including:)](https://developer.apple.com/documentation/swiftui/view/gesture\(_:including:\))
    * [.onLongPressGesture()](https://developer.apple.com/documentation/swiftui/view/onlongpressgesture\(minimumduration:maximumdistance:perform:onpressingchanged:\))
      {% endtab %}

{% tab title="👥 相關" %}

* use [GestureState](/ios/swiftui/gestures/gesturestate.md) to track gesture's state.
  {% endtab %}

{% tab title="❓" %}
{% hint style="warning" %}
問：「 [Long Press Gesture](https://developer.apple.com/documentation/swiftui/longpressgesture) 的 <mark style="color:blue;">`onEnded { finished in ... }`</mark> 事件處理程序會接收一個 <mark style="color:orange;">**finished**</mark> 參數，但問題是：[onEnded](https://developer.apple.com/documentation/swiftui/gesture/onended\(_:\)) 是在<mark style="color:red;">**真正「觸發長按」時**</mark>才會執行，而此時 <mark style="color:orange;">**finished**</mark> 參數似乎總是 <mark style="color:red;">**true**</mark>，所以這是否表示<mark style="color:red;">**此參數根本無用**</mark>❓」
{% endhint %}
{% endtab %}
{% endtabs %}
