我正在开发一款macOS软件,发现在SwiftUI中,如果将scrollview设置为.horizontal
,则鼠标滚轮滚动时列表不会滚动,但在.vertical
模式下可以滚动。
然而,我真的需要这个功能。
所以我尝试了一个选项:使用NSViewRepresentable
实现,创建一个NSView覆盖scrollWheel
方法以处理鼠标滚轮滚动事件,然后发送通知。
struct MouseWheelScrollEventView : NSViewRepresentable {
class MouseView : NSView {
override var acceptsFirstResponder: Bool {
true
}
override func acceptsFirstMouse(for event: NSEvent?) -> Bool {
return true
}
override func scrollWheel(with event: NSEvent) {
NotificationCenter.default.post(name: Notification.Name("mouseevent"), object: event)
}
}
func makeNSView(context: Context) -> some NSView {
let view = MouseView()
DispatchQueue.main.async {
view.window?.makeFirstResponder(view)
}
return view
}
func updateNSView(_ nsView: NSViewType, context: Context) {
print("update")
}
}
然后在SwiftUI中,代码如下:
@available(OSX 11.0, *)
struct ContentView: View {
let mouseWheelScrollEventPublisher = NotificationCenter.default.publisher(for: Notification.Name(rawValue: "mouseevent"))
@State var deltaY = 0.0
@State var currentIndex = 1
var body: some View{
ZStack{
ScrollView(.horizontal,showsIndicators:false) {
ScrollViewReader { value in
LazyHStack(alignment: .top) {
ForEach(1...100, id: \.self) { index in
if(self.currentIndex == index) {
Text("\(String(index))")
.frame(width: 80, height: 80)
.background(Color.yellow)
.onTapGesture(perform: {
print(index)
})
}else {
Text("\(String(index))")
.frame(width: 80, height: 80)
.background(Color.blue)
.onTapGesture(perform: {
print(index)
})
}
}
}
.onReceive(mouseWheelScrollEventPublisher) { output in
let event = output.object as! NSEvent
let deltaY = event.deltaY
if(deltaY < 0 && self.currentIndex < 100) {
self.currentIndex += 1
value.scrollTo(currentIndex)
}else if(deltaY > 0 && self.currentIndex > 1) {
self.currentIndex -= 1
value.scrollTo(currentIndex)
}
}
}
}
.frame(width: 600)
MouseWheelScrollEventView()
}
}
}
现在可以在.horizontal
的scrollView中处理滚动事件,但是有一个新问题:scrollViewItem无法处理点击事件,因为MouseWheelScrollEventView
处理鼠标点击事件。但我想让scrollViewItem也能处理鼠标点击事件。
如何同时处理鼠标滚轮滚动事件和点击事件?
ps:我知道使用appkit可以解决这个问题,但是否有办法尝试使用swiftui实现呢?