Skip to content

Instantly share code, notes, and snippets.

@danhalliday
Created July 31, 2020 19:27
Show Gist options
  • Save danhalliday/62ef0565579cf839d28c5193da70c988 to your computer and use it in GitHub Desktop.
Save danhalliday/62ef0565579cf839d28c5193da70c988 to your computer and use it in GitHub Desktop.
import SwiftUI
struct TappableView: UIViewRepresentable {
let onTap: () -> Void
let onPress: (Bool) -> Void
func makeUIView(context: Context) -> UIView {
TappableUIView(onTap: onTap, onPress: onPress)
}
func updateUIView(_ uiView: UIView, context: Context) {}
}
class TappableUIView: UIView, UIGestureRecognizerDelegate {
let onTap: () -> Void
let onPress: (Bool) -> Void
init(onTap: @escaping () -> Void, onPress: @escaping (Bool) -> Void) {
self.onTap = onTap
self.onPress = onPress
super.init(frame: .zero)
backgroundColor = .clear
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func didMoveToWindow() {
super.didMoveToWindow()
addTapRecognizer()
addPressRecognizer()
removeTouchDelay(view: self)
}
func addTapRecognizer() {
let recognizer = UITapGestureRecognizer()
recognizer.delegate = self
recognizer.addTarget(self, action: #selector(handleTap))
addGestureRecognizer(recognizer)
}
func addPressRecognizer() {
let recognizer = UILongPressGestureRecognizer()
recognizer.minimumPressDuration = 0
recognizer.delegate = self
recognizer.addTarget(self, action: #selector(handlePress))
addGestureRecognizer(recognizer)
}
func removeTouchDelay(view: UIView) {
guard view is UIWindow == false else {
return
}
view.gestureRecognizers?.forEach { recognizer in
recognizer.delaysTouchesBegan = false
}
if let parent = view.superview {
removeTouchDelay(view: parent)
}
}
@objc fileprivate func handleTap(_ sender: UIGestureRecognizer) {
switch sender.state {
case .ended: onTap()
default: ()
}
}
@objc fileprivate func handlePress(_ sender: UIGestureRecognizer) {
switch sender.state {
case .possible, .began, .changed: onPress(true)
case .ended, .cancelled, .failed: onPress(false)
@unknown default: onPress(false)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
onPress(true)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment