告别 Gesture.onEnded(_:),拥抱 SwiftUI 中手势识别的优雅之道
2024-01-28 19:18:42
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(_:) 相关的意外行为。