Recognize both UILongPressGestureRecognizer and UIPanGestureRecognizer on same UIButton - ios

I want to make a UIButton that when you long press it, it will start recording video and if you pan your finger vertically up (while still long pressing), the video will zoom in.
To my button I added a UILongPressGestureRecognizer and a UIPanGestureRecognizer that does just that. Individually, they work. However, they do not work together.
How can I make my button record when long pressing but also allow me to pan my finger and have that recognized as well? This is how I added my recognizers:
let long = UILongPressGestureRecognizer(target: self, action: #selector(record(gesture:)))
button.addGestureRecognizer(long)
let pan = UIPanGestureRecognizer(target: self, action: #selector(zoom(pan:)))
button.addGestureRecognizer(pan)

You need to confirm the delegate of those two gestures.
for ex:
let long = UILongPressGestureRecognizer(target: self, action: #selector(record(gesture:)))
long.delegate = self
button.addGestureRecognizer(long)
let pan = UIPanGestureRecognizer(target: self, action: #selector(zoom(pan:)))
pan.delegate = self
button.addGestureRecognizer(pan)
and there is a delegate method to recognize multiple gestures simultaneously.
gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
define that in your class and return true.
you will get what you want.

I know this wasn't exactly what the question was asking but you can actually bypass having to use gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) and use UILongPressGestureRecognizer as a UIPanGestureRecognizer using the UIGestureRecognizer.State changes. Thats what i've done in the past, cleans things up and makes more logical sense than having two gesture recognizers

Related

How to start drag immediately using UIDragInteraction?

I'm using UIDragInteraction and it works perfectly.
let dragInteraction = UIDragInteraction(delegate: self)
myView.addInteraction(dragInteraction)
dragInteraction.isEnabled = true
As intended, the drag starts when I make a long press on myView. I now want to change this behavior. Instead of long press, I want the drag to start immediately on touching myView and moving my finger?
I've tried using a pan gesture to initiate the move but I don't know how to get the dragInteraction to start.
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panAction))
panGesture.minimumNumberOfTouches = 1
panGesture.maximumNumberOfTouches = 1
panGesture.cancelsTouchesInView = false
panGesture.delaysTouchesBegan = false
myView.addGestureRecognizer(panGesture)
Please help. Thanks.
This does not seem to be possible at the moment with the standard drag and drop implementation.
You could lower the minimumPressDuration of the UILongPressGestureRecognizer associated with the UIDragInteraction though. Further explanation for this can be found in this answer: set minimumPressDuration for UIDragInteraction
In addition to that you can always implement your own drag and drop interaction by using gesture recognizers, etc.. This might of course be tedious and not what you want.
Decrease the long-press duration right after adding the drag interaction:
myView.gestureRecognizers?.compactMap({ $0 as? UILongPressGestureRecognizer}).forEach { recognizer in
recognizer.minimumPressDuration = .leastNonzeroMagnitude
}

Adding gestures to a draggable view? Swift

I've got buttons on my view that are draggable using touches began/moved/ended.
I want to add a tapped and doubletapped actions for my buttons. Once I switch my button's class to UIButton the action I've created works, but once I change it back to DraggableView the actions stop being called because I guess touchesBegan overrides any other touches on the view.
Is there a good way to do this?
First of all you have to implement UITapGestureRecogizer delegate in your class and add following line of code.
let tap = UITapGestureRecognizer(target: self, action: "handleTap:")
tap.delegate = self
tap.numberOfTapsRequired = 1
yourButton.addGestureRecognizer(tap)
Hope this helps.

Gesture Recogniser for all events

I have this piece of code
let window = UIApplication.sharedApplication().keyWindow
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
window?.addGestureRecognizer(tap)
It only recognizes Tap (as its tap gesture recognizer), however I want some recognizer to work for all, scroll, pinch, etc.
Also at later point of time I am removing this recognizer.
I read touches began, but how to use it on UIApplication.sharedApplication().keyWindow?
And how to remove that touches began later?
If you want to monitor all touch event then you can subclass UITapGestureRecognizer, this link should help: Monitoring all iOS touches

Long Press Gesture Recognizer Only Fired When Finger is Lifted

I'm having an interesting problem with a long press gesture recognizer. I placed one of these on a UITableView, and it only works when I lift my finger after the long press. So basically, I would place my finger on a cell, and then when I lift my finger, it triggers the long press. I figured this out by putting printns when the long press began and ended and both fire after I lift my finger. I think the tableViews default panGestureRecognizer might be interfering with the longPressGestureRecognizer. Here is my code in viewDidLoad:
var longPress:UILongPressGestureRecognizer = UILongPressGestureRecognizer(target: self, action: "handleLongPress:")
longPress.minimumPressDuration = 0.06
longPress.delegate = self
self.tableView.addGestureRecognizer(longPress)
longPress.requireGestureRecognizerToFail(self.tableView.panGestureRecognizer)
Touching down in the cell will not cause the table view's panGestureRecognizer to fail, so delete the requireGestureRecognizerToFail method, and you should then get to the .Began state while your finger is still down.

How to detect a flick gesture using UISwipeGestureRecognizer?

I heard that UISwipeGestureRecognizer can be used to distinguish between a slow swipe and a fast flick. But I can't find any API to tell the difference.
Do you specifically need to use UISwipeGestureRecognizer, or can you use UIPanGestureRecognizer instead? UIPanGestureRecognizer gives you precise movement data whereas UISwipeGestureRecognizer is more basic and just detects whether or not a swipe happened (and in which direction).
UIPanGestureRecognizer has a -velocityInView: method which returns a CGPoint, expressing points per second, vertically and horizontally.
You should use Pan Gesture and find out velocity for better accuracy.
Here is code snip for PanGesture in Swift 5
//Add Pan Gesture on target view in viewDidLoad
let panGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.panGestureDetected))
view.addGestureRecognizer(panGesture)
#objc func panGestureDetected()
{
print("Pan Gesture detected!!")
}

Resources