I want to
- Detect global touch up event anywhere in the screen
- Will not affect components like buttons, custom views underneath. The underneath buttons, custom views are still able to receive the tap event.
What I did is
- Install
UITapGestureRecognizer
inUIApplication.shared.keyWindow
- In
UIGestureRecognizerDelegate
, returnstrue
forshouldRecognizeSimultaneouslyWith
, so that the top level keyWindow will not block buttons, custom views from receiving the tap event.
This is my code
import UIKit
extension UIWindow {
static var key: UIWindow! {
if #available(iOS 13, *) {
return UIApplication.shared.windows.first { $0.isKeyWindow }
} else {
return UIApplication.shared.keyWindow
}
}
}
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer)
-> Bool {
print(">>> shouldRecognizeSimultaneouslyWith returns true")
return true
}
}
class ViewController: UIViewController {
// Lazy is required as self is not ready yet without lazy.
private lazy var globalGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(globalTapped))
private func installGlobalGestureRecognizer() {
UIWindow.key.removeGestureRecognizer(globalGestureRecognizer)
UIWindow.key.addGestureRecognizer(globalGestureRecognizer)
globalGestureRecognizer.delegate = self
}
@objc func globalTapped() {
print(">>> global tapped")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func buttonClicked(_ sender: Any) {
print("yellow button tap\n")
}
@IBAction func handleTap(_ gesture: UITapGestureRecognizer) {
print("red view tap\n")
}
@IBAction func installButtonClicked(_ sender: Any) {
print("install global gesture")
installGlobalGestureRecognizer()
}
}
This is what happens when the red custom view being tapped
When red custom view being tapped (Work as expected)
install global gesture
>>> shouldRecognizeSimultaneouslyWith returns true
>>> shouldRecognizeSimultaneouslyWith returns true
>>> global tapped
red view tap
When the yellow button is being tapped (Global gesture not working)
install global gesture
yellow button tap
This is how I install the tap event handler, for both custom red view and yellow button.
Does anyone have any idea, why shouldRecognizeSimultaneouslyWith
is not called, when the button is tapped? I expect when tapping on the yellow button
shouldRecognizeSimultaneouslyWith
executed and returns true- yellow button tap event handler executed
- global gesture tap event handler executed
Thanks.