SwiftUI中如何阻止DragGesture修改光标或指定其使用的光标?
SwiftUI中为Divider拖拽手势指定自定义光标
SwiftUI的DragGesture默认会在拖拽过程中将光标切换为pointingHand,这确实不符合左右调整尺寸的交互预期。下面提供两种可行的解决方案,替代你当前的临时实现:
方案一:自定义NSViewRepresentable分隔线(彻底控制光标)
通过包装NSView来实现可拖拽的分隔线,完全接管手势和光标逻辑,避免系统默认行为的干扰:
import SwiftUI struct ResizableDivider: NSViewRepresentable { @Binding var width: CGFloat let minWidth: CGFloat = 150 func makeNSView(context: Context) -> NSView { let view = NSView() view.frame.size.height = 1 view.backgroundColor = .separatorColor let panGesture = NSPanGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handlePan(_:))) view.addGestureRecognizer(panGesture) return view } func updateNSView(_ nsView: NSView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject { let parent: ResizableDivider init(_ parent: ResizableDivider) { self.parent = parent } @objc func handlePan(_ gesture: NSPanGestureRecognizer) { let translation = gesture.translation(in: gesture.view) switch gesture.state { case .began: NSCursor.resizeLeftRight.push() case .changed: parent.width = max(parent.minWidth, parent.width + translation.x) gesture.setTranslation(.zero, in: gesture.view) case .ended, .cancelled: NSCursor.pop() default: break } } } } // 使用示例 struct ContentView: View { @State private var width: CGFloat = 200 var body: some View { HStack(spacing: 0) { ViewA().frame(width: width) ResizableDivider(width: $width) ViewB().frame(maxWidth: .infinity) } } }
方案二:修复原生SwiftUI手势的光标冲突
如果想继续使用原生Divider和DragGesture,可以修正光标管理逻辑,强制覆盖系统默认的pointingHand:
HStack(spacing: 0) { ViewA().frame(width: self.width, alignment: .leading) Divider() .onHover { isHovering in isHovering ? NSCursor.resizeLeftRight.push() : NSCursor.pop() } .gesture( DragGesture(minimumDistance: 0) .onChanged { value in self.width = max(150, self.width + value.translation.width) // 持续push光标,覆盖系统自动设置的pointingHand NSCursor.resizeLeftRight.push() } .onEnded { _ in NSCursor.pop() } ) ViewB().frame(maxWidth: .infinity, alignment: .trailing) }
注意:原代码使用VStack可能是笔误,左右调整宽度应该用HStack;同时修正了onHover的光标逻辑,确保hover和拖拽状态下都显示resizeLeftRight。
两种方案对比:
- 方案一:交互更稳定,无系统行为干扰,适合需要扩展更多自定义逻辑的场景
- 方案二:代码更简洁,依赖SwiftUI原生组件,但需要通过重复push光标来覆盖系统默认行为
内容的提问来源于stack exchange,提问作者beeselmane
相关产品推荐
相关产品推荐

