And*_*rew 5 macos swift swiftui
我对 2 指滑动(滚动)手势感兴趣。
不是两指拖动,而是两指滑动(无需按下)。就像在 Safari 中用来向上和向下滚动一样。
据我所知,没有一个基本手势可以用于此目的:TapGesture - 不是;LongPressGesture - 不;DragGesture - 不;MagnificationGesture - 不;RotationGesture - 不;
有人知道如何做到这一点吗?
我至少需要看方向。
充分尊重 @duncan-c 的答案,更有效的方法是使用NSResponder的scrollWheel(with: NSEvent)来跟踪两根手指滚动(一根手指在 Apple 鼠标上)。
然而它仅在 下可用NSView,因此您需要使用 将其集成到 SwiftUI 中NSRepresentableView。
这是一组完整的工作代码,使用滚轮滚动主图像。该代码使用委托和回调将滚动事件沿链传递回 SwiftUI:
\n//\n// ContentView.swift\n// ScrollTest\n//\n// Created by TR Solutions on 6/9/21.\n//\n\nimport SwiftUI\n\n/// How the view passes events back to the representable view.\nprotocol ScrollViewDelegateProtocol {\n /// Informs the receiver that the mouse\xe2\x80\x99s scroll wheel has moved.\n func scrollWheel(with event: NSEvent);\n}\n\n/// The AppKit view that captures scroll wheel events\nclass ScrollView: NSView {\n /// Connection to the SwiftUI view that serves as the interface to our AppKit view.\n var delegate: ScrollViewDelegateProtocol!\n /// Let the responder chain know we will respond to events.\n override var acceptsFirstResponder: Bool { true }\n /// Informs the receiver that the mouse\xe2\x80\x99s scroll wheel has moved.\n override func scrollWheel(with event: NSEvent) {\n // pass the event on to the delegate\n delegate.scrollWheel(with: event)\n }\n}\n\n/// The SwiftUI view that serves as the interface to our AppKit view.\nstruct RepresentableScrollView: NSViewRepresentable, ScrollViewDelegateProtocol {\n /// The AppKit view our SwiftUI view manages.\n typealias NSViewType = ScrollView\n \n /// What the SwiftUI content wants us to do when the mouse's scroll wheel is moved.\n private var scrollAction: ((NSEvent) -> Void)?\n \n /// Creates the view object and configures its initial state.\n func makeNSView(context: Context) -> ScrollView {\n // Make a scroll view and become its delegate\n let view = ScrollView()\n view.delegate = self;\n return view\n }\n \n /// Updates the state of the specified view with new information from SwiftUI.\n func updateNSView(_ nsView: NSViewType, context: Context) {\n }\n \n /// Informs the representable view that the mouse\xe2\x80\x99s scroll wheel has moved.\n func scrollWheel(with event: NSEvent) {\n // Do whatever the content view wants\n // us to do when the scroll wheel moved\n if let scrollAction = scrollAction {\n scrollAction(event)\n }\n }\n\n /// Modifier that allows the content view to set an action in its context.\n func onScroll(_ action: @escaping (NSEvent) -> Void) -> Self {\n var newSelf = self\n newSelf.scrollAction = action\n return newSelf\n }\n}\n\n/// Our SwiftUI content view that we want to be able to scroll.\nstruct ContentView: View {\n /// The scroll offset -- when this value changes the view will be redrawn.\n @State var offset: CGSize = CGSize(width: 0.0, height: 0.0)\n /// The SwiftUI view that detects the scroll wheel movement.\n var scrollView: some View {\n // A view that will update the offset state variable\n // when the scroll wheel moves\n RepresentableScrollView()\n .onScroll { event in\n offset = CGSize(width: offset.width + event.deltaX, height: offset.height + event.deltaY)\n }\n }\n /// The body of our view.\n var body: some View {\n // What we want to be able to scroll using offset(),\n // overlaid (must be on top or it can't get the scroll event!)\n // with the view that tracks the scroll wheel.\n Image(systemName:"applelogo")\n .scaleEffect(20.0)\n .frame(width: 200, height: 200, alignment: .center)\n .offset(offset)\n .overlay(scrollView)\n }\n}\n\nstruct ContentView_Previews: PreviewProvider {\n static var previews: some View {\n ContentView()\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
import Combine
@main
struct MyApp: App {
@State var subs = Set<AnyCancellable>() // Cancel onDisappear
@SceneBuilder
var body: some Scene {
WindowGroup {
SomeWindowView()
/////////////
// HERE!!!!!
/////////////
.onAppear { trackScrollWheel() }
}
}
}
/////////////
// HERE!!!!!
/////////////
extension MyApp {
func trackScrollWheel() {
NSApp.publisher(for: \.currentEvent)
.filter { event in event?.type == .scrollWheel }
.throttle(for: .milliseconds(200),
scheduler: DispatchQueue.main,
latest: true)
.sink {
if let event = $0 {
if event.deltaX > 0 { print("right") }
if event.deltaX < 0 { print("left") }
if event.deltaY > 0 { print("down") }
if event.deltaY < 0 { print("up") }
}
}
.store(in: &subs)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4400 次 |
| 最近记录: |