正如您已经发现的,LongPressGesture
在触发它所需的时间间隔过go 时结束,而不是在用户竖起手指时结束.因此,它不适合于检测手指抬起.
我会用DragGesture
来代替.它的onChanged
在手势开始时被调用,而它的onEnded
在手指抬起时被调用.我们可以在onChanged
中记录开始时间,在onEnded
中记录结束时间,从而记录用户已经按下了多长时间.
@State var touchDownTime: Date?
@State var impactTrigger = false
var body: some View {
Color.yellow
.simultaneousGesture(
DragGesture(minimumDistance: 0)
.onChanged({ value in
if touchDownTime == nil {
touchDownTime = value.time
impactTrigger.toggle()
print("Started")
}
})
.onEnded({ value in
if let touchDownTime,
value.time.timeIntervalSince(touchDownTime) >= 1 {
impactTrigger.toggle()
print("Ended")
}
self.touchDownTime = nil
})
)
.sensoryFeedback(.impact(weight: .light), trigger: impactTrigger)
}
请注意,我已经将其更改为使用sensoryFeedback
来创建触觉反馈.如果你的目标是比iOS 17更旧的版本,使用UIImpactFeedbackGenerator
也可以.
请注意,与LongPressGesture
不同的是,当用户按下手指后移动太多时不会触发,而如果手指移动,DragGesture
仍然可以识别.如果这是不需要的,请使用value.translation
属性来确定手指是否移动太多.
@State var shouldCancel = false
...
.onChanged({ value in
...
let threshold: CGFloat = 10 // decide a threshold
if hypot(value.translation.width, value.translation.height) > threshold {
shouldCancel = true
}
})
.onEnded({ value in
if let touchDownTime,
!shouldCancel, // <----
value.time.timeIntervalSince(touchDownTime) >= 1 {
impactTrigger.toggle()
print("Ended")
}
self.touchDownTime = nil
shouldCancel = false
})