如何避免DragGesture触发时NSWindow随滑块拖动移动?
解决SwiftUI滑块拖拽时NSWindow随之移动的问题
针对你遇到的滑块拖拽触发窗口移动的问题,这里提供两种可靠的解决方式:
方法一:使用高优先级手势(推荐)
SwiftUI中,.highPriorityGesture会让当前视图的手势优先于窗口的拖拽手势被识别,直接阻止事件传递给窗口。只需将原代码中的.gesture替换为.highPriorityGesture,同时可以移除设置窗口isMovable的冗余逻辑:
修改后的核心代码片段:
.highPriorityGesture( DragGesture(minimumDistance: 0) .onChanged { v in if (abs(v.translation.width) < 0.1) { self.lastCoordinateValue = sliderVal } if v.translation.width > 0 { let nextCoordinateValue = min(maxValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } else { let nextCoordinateValue = max(minValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } } )
方法二:优化窗口可移动状态设置(兼容旧场景)
如果需要保留设置窗口isMovable的方式,需通过异步调度确保状态及时更新,避免手势识别延迟导致窗口误移动:
修改后的手势逻辑:
.gesture( DragGesture(minimumDistance: 0) .onChanged { v in DispatchQueue.main.async { self.currentWindow?.isMovable = false } if (abs(v.translation.width) < 0.1) { self.lastCoordinateValue = sliderVal } if v.translation.width > 0 { let nextCoordinateValue = min(maxValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } else { let nextCoordinateValue = max(minValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } } .onEnded({ _ in DispatchQueue.main.async { self.currentWindow?.isMovable = true } }) )
完整修改后的MusicPlaySlider代码
struct MusicPlaySlider: View { @Environment(\.currentWindow) private var currentWindow @Binding var value: Double @State var lastCoordinateValue: CGFloat = 0.0 var sliderRange: ClosedRange<Double> = 1...100 var thumbColor: Color = .white var minTrackColor: Color = .white var maxTrackColor: Color = .black.opacity(0.4) var body: some View { GeometryReader { gr in let thumbHeight = gr.size.height * 1.1 let thumbWidth = gr.size.width * 0.03 let radius = gr.size.height * 0.15 let minValue = gr.size.width * 0.015 let maxValue = (gr.size.width * 0.98) - thumbWidth let scaleFactor = (maxValue - minValue) / (sliderRange.upperBound - sliderRange.lowerBound) let lower = sliderRange.lowerBound let sliderVal = (self.value - lower) * scaleFactor + minValue ZStack { Rectangle() .foregroundColor(maxTrackColor) .frame(width: gr.size.width, height: gr.size.height * 0.95) .clipShape(RoundedRectangle(cornerRadius: radius)) HStack { Rectangle() .foregroundColor(minTrackColor) .frame(width: sliderVal, height: gr.size.height * 0.95) Spacer() } .clipShape(RoundedRectangle(cornerRadius: radius)) HStack { RoundedRectangle(cornerRadius: 1) .foregroundColor(thumbColor) .frame(width: thumbWidth, height: thumbHeight) .offset(x: sliderVal) Spacer() } } .highPriorityGesture( DragGesture(minimumDistance: 0) .onChanged { v in if (abs(v.translation.width) < 0.1) { self.lastCoordinateValue = sliderVal } if v.translation.width > 0 { let nextCoordinateValue = min(maxValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } else { let nextCoordinateValue = max(minValue, self.lastCoordinateValue + v.translation.width) self.value = ((nextCoordinateValue - minValue) / scaleFactor) + lower } } ) } } }
内容的提问来源于stack exchange,提问作者jrjian
相关产品推荐
相关产品推荐

