SwiftUI的手势(如highPriorityGesture),在使用的过程中可能会被子视图的手势覆盖,因此可以借助UIKit进行处理。
基本逻辑为,在Window层级添加手势识别器,识别所有类型的触摸,当Window上的UITapGestureRecognizer监测到触摸时,调用shouldReceive方法,触摸继续向下传递给子视图。
解决方案
1、创建一个专门管理手势的类:
class GlobalTouchManager: NSObject, UIGestureRecognizerDelegate {
static let shared = GlobalTouchManager()
var onTouch: (() -> Void)?
func setup() {
guard let window = UIApplication.shared.windows.first else { return }
let gesture = UITapGestureRecognizer()
gesture.cancelsTouchesInView = false
gesture.requiresExclusiveTouchType = false
gesture.delegate = self
window.addGestureRecognizer(gesture)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldReceive touch: UITouch) -> Bool {
onTouch?()
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
2、SwiftUI视图:
Home()
.onAppear {
GlobalTouchManager.shared.onTouch = {
print("点击屏幕")
}
GlobalTouchManager.shared.setup()
}
当点击视图时,会输出:点击屏幕。
onTouch闭包可以传递点击后调用的方法,不会干扰其他控件,也不会和NavigationLink返回按钮存在冲突。
总结
SwiftUI手势本质上是封装UIKit的UIGestureRecognizer手势,因此可以通过UIKit对触摸进行监测,从而实现检测屏幕点击事件的效果。
参考文章
1、SwiftUI检测屏幕点击事件:https://stackoverflow.com/questions/62400806/detect-and-forward-taps-anywhere-on-screen-in-swiftui
