iOS: recognize pinch gestures but not two finger pans? - ios

The goal is to only let pinch gestures get recognized if a two-finger pan is not in process.
This code allows both pinchGesture and two-finger panGestures, but they occur at the same time. This was based off this answer to use the gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) function.
// Handle two-finger pans
let twoFingerPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(sceneViewPannedTwoFingers))
twoFingerPanRecognizer.minimumNumberOfTouches = 2
twoFingerPanRecognizer.maximumNumberOfTouches = 2
twoFingerPanRecognizer.delegate = self
sceneView.addGestureRecognizer(twoFingerPanRecognizer)
// Handle pinches
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(sceneViewPinched))
pinchGesture.delegate = self
sceneView.addGestureRecognizer(pinchGesture)
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer is UIPinchGestureRecognizer {
return false
} else {
return true
}
}
This code allows two-finger pans, but pinches do not work at all.
// Handle two-finger pans
let twoFingerPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(sceneViewPannedTwoFingers))
twoFingerPanRecognizer.minimumNumberOfTouches = 2
twoFingerPanRecognizer.maximumNumberOfTouches = 2
twoFingerPanRecognizer.delegate = self
sceneView.addGestureRecognizer(twoFingerPanRecognizer)
// Handle taps
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(sceneViewTapped))
sceneView.addGestureRecognizer(tapRecognizer)
// Handle pinches
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(sceneViewPinched))
pinchGesture.delegate = self
pinchGesture.requireGestureRecognizerToFail(twoFingerPanRecognizer)
sceneView.addGestureRecognizer(pinchGesture)
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}

Have you try like this
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if ((gestureRecognizer is UIPinchGestureRecognizer || gestureRecognizer is UIPanGestureRecognizer)
&& (otherGestureRecognizer is UIPinchGestureRecognizer || otherGestureRecognizer is UIPanGestureRecognizer)) {
return false
}
return true
}

Related

How to resolve the Gesture conflict with webView and its subview?

I want to add double click gesture to my webview, but not intercept its own click callback,I a subview to response double click gesture , but click callback of the webview will be invalid
{
webMaskView = UIView()
webVie w.addSubview(webMaskView)
webMaskView.snp.makeConstraints { (make) in
make.left.right.top.bottom.equalTo(webV)
}
let doubleTap = UITapGestureRecognizer(target: self, action: #selector(webViewTwoTaped(_ :)))
doubleTap.delegate = self
doubleTap.numberOfTapsRequired = 2
webMaskView.addGestureRecognizer(doubleTap)
webMaskView.isUserInteractionEnabled = true
webMaskView.backgroundColor = UIColor.blue.withAlphaComponent(0.1)
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return true
}
override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
You no need to add subview for double tap gesture, You can add double tap gesture directly on Webview or WKWebView.

Fast tap gestures in Swift 4 and iOS 11

I just made a simple app to try out any type of gestures. I got to the tap gesture. So I thought, what if I made a fast tap game kind of application that counts the amount of taps the user performed. But soon enough I ran into some issues.
It did not count all the taps. If I began to tap as fast as possible, but it skipped taps.
The idea is I programmatically created a view in the superview and added a tapGestureRecognizer on the view. And simply put the “taps” into a label in the app.
It seems to fail to receive a system gesture on time.
The code:
let tap = UITapGestureRecognizer(target: self, action: #selector(tapped(sender:)));
tap.numberOfTapsRequired = 1;
animationView.isUserInteractionEnabled = true;
animationView.addGestureRecognizer(tap);
The function:
#objc func tapped (sender :UITapGestureRecognizer) {
self.counter += 1;
self.lblScore.text = String(self.counter);
}
I have an animationView that I made "tappable" and it works. Every time I tap the animationView it increments the value of 'counter' that works! but every time I get this error if I tap too fast:
<_UISystemGestureGateGestureRecognizer: 0x1c01c4b00>: Gesture: Failed to receive system gesture state notification before next touch
Create Gesture :
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
panGesture.delegate = self
Button.addGestureRecognizer(panGesture)
let longTapGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleLongTapGesture(_:)))
Button.addGestureRecognizer(longTapGesture)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
Button.addGestureRecognizer(tapGesture)
let rotateGesture = UIRotationGestureRecognizer(target: self, action: #selector(handleRotateGesture(_:)))
rotateGesture.delegate = self
Button.addGestureRecognizer(rotateGesture)
let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(handlePinchGesture(_:)))
pinchGesture.delegate = self
Button.addGestureRecognizer(pinchGesture)
Gesture click Event :
extension AddTextVC: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
#IBAction func handlePanGesture(_ recognizer: UIPanGestureRecognizer) {
}
#IBAction func handlePinchGesture(_ recognizer: UIPinchGestureRecognizer) {
}
#IBAction func handleRotateGesture(_ recognizer: UIRotationGestureRecognizer)
{
}
#IBAction func handleTapGesture(_ recognizer: UITapGestureRecognizer) {
}
#IBAction func handleLongTapGesture(_ recognizer: UITapGestureRecognizer) {
}
}

tap gesture is not working when i touch my player( MPMovieplayerController)

here i try to merge all video and display that video in screen. but i need to add tap gesture when i press the player screen it should handle some action. but if i tab on view its working but if i tap on player its not working. any solution please
EDITED:
class ViewController: UIViewController,UIGestureRecognizerDelegate {
var location: CGPoint!
var gestureRecognizer: UITapGestureRecognizer!
var videoPlayer = MPMoviePlayerController()
override func viewDidLoad() {
super.viewDidLoad()
musicImg.hidden = true
let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTapGesture")
gestureRecognizer.delegate = self;
videoPlayer.view.addGestureRecognizer(gestureRecognizer)
}
func handleTap(gestureRecognizer: UIGestureRecognizer) {
//location = gestureRecognizer .locationInView(videoPlayer.view)
print("tapped")
}
//#pragma mark - gesture delegate
// this allows you to dispatch touches
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Displaying my selected video in screen:
self.mediaUI.dismissViewControllerAnimated(true, completion: nil)
self.videoPlayer = MPMoviePlayerController()
self.videoPlayer.contentURL = self.videoURL
self.videoPlayer.controlStyle = .Embedded
self.videoPlayer.scalingMode = .AspectFill
self.videoPlayer.shouldAutoplay = true
self.videoPlayer.backgroundView.backgroundColor = UIColor.clearColor()
self.videoPlayer.fullscreen = true
self.videoPlayer.view.frame = CGRectMake(38, 442, 220, 106)
self.view.addSubview(self.videoPlayer.view)
self.videoPlayer.play()
self.videoPlayer.prepareToPlay()
My screen in fully white, no button,label are showing
Try with this...
let gestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "handleTapGesture")
gestureRecognizer.delegate = self;
If you want to add gesture in movie player controller
videoPlayer.view.addGestureRecognizer(gestureRecognizer)
and if you want for main screen...
self.view.addGestureRecognizer(gestureRecognizer)
And implement delegate methods
#pragma mark - gesture delegate
// this allows you to dispatch touches
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return true
}
// this enables you to handle multiple recognizers on single view
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer touch: UITouch) -> Bool {
return true
}

Swift UIGestureRecognizer Touchdown

Is it possible to capture touchdown and longpress with UIGestureRecognizer?
func gestureSetup() {
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "tapButton:")
tapTempoButton.addGestureRecognizer(tapGestureRecognizer)
let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: "longPressed:")
longPressRecognizer.minimumPressDuration = 1.0
tapTempoButton.addGestureRecognizer(longPressRecognizer)
}
func tapButton(sender: UITapGestureRecognizer) {
// On touch down update UI and play sound
}
example: Gestures on UITextLabel
//Called on Label
let rotationGesture = UIRotationGestureRecognizer(target: self, action: "handleRotation:")
rotationGesture.delegate = self
let tapToDeleteTextGesture = UITapGestureRecognizer(target: self, action: "tapToDeleteText:")
tapToDeleteTextGesture.numberOfTapsRequired = 2
textLabel?.addGestureRecognizer(rotationGesture)
textLabel?.addGestureRecognizer(tapToDeleteTextGesture)
func handleRotation(recognizer: UIRotationGestureRecognizer){
let state = recognizer.state
if (state == UIGestureRecognizerState.Began || state == UIGestureRecognizerState.Changed){
if let view = recognizer.view {
view.transform = CGAffineTransformRotate(view.transform, recognizer.rotation)
recognizer.rotation = 0
}
}
}
func tapToDeleteText(recognizer: UITapGestureRecognizer){
if let view = recognizer.view {
view.removeFromSuperview()
}
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
Add add the longPressGesture and you'll be set.

Detect UIScreenEdgeGestureRecognizer and fail UIPanGestureRecognizer

In my ViewController I have a UIScreenEdgeGestureRecognizer for switching views but also a UITableView with a custom UITableViewCell. In this custom UITableViewCell is a UIPanGestureRecognizer for swiping the cells.
I added gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: so both of the gestures are working and gestureRecognizerShouldBegin to prevent the conflict of vertical scrolling.
The question is, how can I give the UIScreenEdgeGestureRecognizer priority? When I swipe at the edge of the screen, I want to switch the views without panning the cells. I figured I should be using the delegate methods, but so far the more I read the more confused I'm getting.
Code in custom UITableViewCell:
override func viewDidload() {
var recognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
recognizer.delegate = self
addGestureRecognizer(recognizer)
}
override func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGesture = gestureRecognizer as? UIPanGestureRecognizer {
let velocity = panGesture.velocityInView(superview!)
if fabs(velocity.x) > fabs(velocity.y) { return true }
return false
}
return false
}
ViewController:
override func viewDidLoad() {
let rightScreenEdgeRecognizer = EdgePanGesture(target: self, action: "changeView:")
rightScreenEdgeRecognizer.edges = .Right
view.addGestureRecognizer(rightScreenEdgeRecognizer)
}
I also tried identifying the recognizers with:
gestureRecognizer.isKindOfClass(UIScreenEdgePanGestureRecognizer)
and
gestureRecognizer as? UIScreenEdgePanGestureRecognizer
But all were failed.
Turns out I was looking at the right direction with gestureRecognizer as? UIScreenEdgePanGestureRecognizer but instead of gestureRecognizer I should have used otherGestureRecognizer.
override func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOfGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if let recognizer = otherGestureRecognizer as? UIScreenEdgePanGestureRecognizer {
return true
}
return false
}

Resources