【发布时间】:2021-02-08 08:06:40
【问题描述】:
我正在开发一个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()
}
}
}
现在滚动事件可以在.horizontalscrollView中处理,但是有一个新问题:scrollViewItem不能处理点击事件,因为MouseWheelScrollEventView处理了鼠标点击事件。但是我希望scrollViewItem也能处理鼠标点击事件。
如何处理鼠标滚轮滚动事件和点击事件?
ps:我知道使用appkit可以解决问题,但是有没有办法尝试使用swiftui实现呢?
【问题讨论】:
-
在这里同时使用这两个事件。使用 Xcode 12.0 测试。
-
@Asperi 你的意思是使用我的方法是可以做到的。 1.scrollView 可以处理鼠标滚轮滚动事件 2.scrollView 项可以处理点击事件,我也使用 xcode(版本 12.0 beta 6 (12A8189n))但是 scrollView 项不能处理点击事件。你能告诉我你的代码吗?谢谢