返回

告别 Gesture.onEnded(_:),拥抱 SwiftUI 中手势识别的优雅之道

IOS

SwiftUI 中避免 Gesture.onEnded(_:) 的优雅之道

在 SwiftUI 的手势识别世界中,Gesture.onEnded(_:) 曾经是检测手势完成的可靠方法。然而,随着 SwiftUI 的不断发展,我们发现它在某些情况下可能会导致意想不到的行为。本文旨在探讨这些情况,并提供优雅的替代方案,让您避免 Gesture.onEnded(_:) 的困扰。

Gesture.onEnded(_:) 的局限性

Gesture.onEnded(_:) 依赖于手势的内部状态,即 hasEnded 属性。当手势处于 hasEnded 为 false 的活跃状态时,Gesture.onEnded(_:) 会被调用。然而,在某些情况下,即使手势已经实际结束,Gesture.onEnded(_:) 也不会被触发。这是由于 SwiftUI 在后台对手势进行某些优化所致。

一种常见的情况是当手势与其他手势同时进行时。例如,如果您同时进行一个拖动手势和一个轻按手势,当轻按手势完成时,拖动手势的 hasEnded 属性可能仍然为 false,从而导致 Gesture.onEnded(_:) 未被触发。

优雅的替代方案

为了避免 Gesture.onEnded(_:) 的这些局限性,有几种优雅的替代方案可供选择:

1. 使用 SimultaneousGesture(of:)

SimultaneousGesture(of:) 是一种组合手势,允许您同时检测多个手势。您可以使用它来创建自己的自定义手势,其中包含手势结束时触发的操作。例如:

struct MyGesture: View {
    var body: some View {
        SimultaneousGesture(
            DragGesture().onChanged({ _ in }),
            TapGesture().onEnded({ _ in })
        ) { _,_ in
            // 自定义操作
        }
    }
}

在这种情况下,当轻按手势结束时,自定义操作将被触发,而无需担心拖动手势的内部状态。

2. 使用 when(isActive:)

when(isActive:) 是一个修饰器,可让您根据手势的 isActive 属性控制视图的可见性或启用状态。当手势处于活动状态时,isActive 为 true;当手势完成时,isActive 为 false。例如:

struct MyView: View {
    @State var isGestureActive = false

    var body: some View {
        Button("Button") {
            isGestureActive.toggle()
        }
        .when(isActive: $isGestureActive) {
            // 自定义操作
        }
    }
}

在上面的示例中,当按钮被按下时,isGestureActive 将变为 true,从而显示自定义操作。当按钮被释放时,isGestureActive 将变为 false,从而隐藏自定义操作。

3. 使用 gesture(minimumDuration:)

gesture(minimumDuration:) 是一个修饰器,可让您指定手势触发的最小持续时间。您可以使用它来确保手势不会因意外的快速轻按或拖动而触发。例如:

struct MyView: View {
    var body: some View {
        Button("Button") {
            // 自定义操作
        }
        .gesture(TapGesture(count: 1).minimumDuration(0.5))
    }
}

在这种情况下,手势只有在被按下至少 0.5 秒后才会触发自定义操作。

结论

避免使用 Gesture.onEnded(_:) 可以确保您的 SwiftUI 应用程序中的手势识别更加可靠和可预测。通过使用 SimultaneousGesture(of:)when(isActive:)gesture(minimumDuration:) ,您可以创建自定义手势,在各种情况下都能如期工作。

常见问题解答

1. 什么是 Gesture.onEnded(_:) 的主要问题?

Gesture.onEnded(_:) 依赖于手势的内部状态,这可能导致意外的行为,尤其是当手势与其他手势同时进行时。

2. SimultaneousGesture(of:) 有什么优点?

SimultaneousGesture(of:) 允许您同时检测多个手势,从而创建自定义手势,在各种情况下都能如期工作。

3. when(isActive:) 如何工作?

when(isActive:) 根据手势的活动状态控制视图的可见性或启用状态。当手势处于活动状态时,它将显示自定义操作;当手势完成时,它将隐藏自定义操作。

4. gesture(minimumDuration:) 有什么用?

gesture(minimumDuration:) 允许您指定手势触发的最小持续时间,从而防止手势因意外的快速轻按或拖动而触发。

5. 使用这些替代方案有什么好处?

使用 SimultaneousGesture(of:)when(isActive:)gesture(minimumDuration:) 可以创建更可靠、更可预测的手势识别体验,并避免使用 Gesture.onEnded(_:) 相关的意外行为。