#1 onLongPressGesture
功能
为任意 View 添加长按手势识别。当用户持续按压且达到指定时长、同时手指偏移不超过阈值时,视为一次有效长按;可实时获取按压状态以驱动过渡动画。
参数说明
-
minimumDuration:触发所需最短按压时间(秒)。 -
maximumDistance:手指允许的最大偏移,单位为点;超限即判定为取消。 -
onPressingChanged:按压状态变化回调;true表示按下,false表示抬起或滑出。 -
action:满足时长与偏移条件后执行的一次性回调。
代码示例
struct LongPressGestureBootcamp: View {
@State var isComplete: Bool = false
@State var isSuccess: Bool = false
var body: some View {
VStack {
Rectangle()
.fill(isSuccess ? .green : .blue)
.frame(maxWidth: isComplete ? .infinity : 0)
.frame(height: 56)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.gray)
HStack {
Text("CLICK HERE")
.foregroundStyle(.white)
.padding()
.background(.black)
.cornerRadius(8)
.onLongPressGesture(
minimumDuration: 1.0,
maximumDistance: 56) { (isPressing) in
// start of press -> min duration
if isPressing {
withAnimation(.easeInOut(duration: 1.0)) {
isComplete = true
}
}
else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
if !isSuccess {
withAnimation(.easeInOut) {
isComplete = false
}
}
}
}
} perform: {
// at the min duration
withAnimation(.easeInOut) {
isSuccess = true
}
}
Text("RESET")
.foregroundStyle(.white)
.padding()
.background(.black)
.cornerRadius(8)
.onTapGesture {
isComplete = false;
isSuccess = false;
}
}
}
// Text(isComplete ? "COMPLETED" : "NOT COMPLETE")
// .padding()
// .background(isComplete ? .green : .gray)
// .cornerRadius(8)
//// .onTapGesture {
//// withAnimation {
//// isComplete.toggle()
//// }
//// }
// .onLongPressGesture(minimumDuration: 1.0, maximumDistance: 50, perform: {
// isComplete.toggle()
// })
}
}
注意事项
- 若同时附加
.onTapGesture,长按结束后可能额外触发一次点按,应通过状态标志互斥。 - 在
onPressingChanged中更新界面时,请使用withAnimation保证过渡流畅。 - 耗时操作请置于
action的异步闭包内,避免阻塞主线程。