I am using three gesture named Pan, Pinch and Rotate. I want To use Pinch and Rotate gesture together and Pan separate. I am using gestureDelegate method like below :
func gestureRecognizer(_: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer:UIGestureRecognizer) -> Bool
{
return true
}
But it runs thrice. I want two Simultaneously.
If you have implemented this single method shouldRecognizeSimultaneouslyWithGestureRecognizer of UIGestureRecognizerDelegate than simply remove the delegate of UIPanGestureRecognizer or could not set it.
Related
In my iOS app I have an instance of an MKMapView and on single tap, I want to add a marker to the map. I've added a UITapGestureRecognizer and immediately noticed that it would fire even when a user double taps to zoom (or other interactions with the map).
I've implemented the UIGestureRecognizerDelegate method like this and this works, but makes the interaction very sluggish, because it obviously waits for the other gesture recognizers to fail.
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
guard gestureRecognizer == self.mapGestureRecognizer else {
return false
}
return !(otherGestureRecognizer is UITapGestureRecognizer) && otherGestureRecognizer.state == .possible
}
Is there any way to act quickly on a tap, without breaking the native gestures on the map view?
Not sure there is a direct solution to this as the mapView can't know if your tap is part of another gesture until it's waited to check. My usual workaround for this is to use a long tap for adding markers to the map as this is a discrete event
I have the following case. parentView has it's own gestureRecognizerAand has a subview subView which has it's own UITapGestureRecognizer.
Is there any way to tell parentView that it should pass the touch events recognized in gestureRecognizerA to subView if these touch events are in subView's bounds?
gestureRecognizerA is very specific. It is a custom gesture recognizer for recognizing a circlular motion. This recognition should happen on all areas of parentView. However, when that same gesture recognizer recognizes a tap, it should pass that tap to subView.
You can easily identify the points of tap.
As for example you have a tap gesture in parent class as:
let tapGR = UITapGestureRecognizer(target: self, action: #selector(tapped))
view.addGestureRecognizer(tapGR)
#objc func tapped(gr:UITapGestureRecognizer) {
let loc:CGPoint = gr.location(in: gr.view)
//insert your touch based code here
}
Inside the tapped method you can identify the location where tap happened, so after checking bounds of the subview with location of tap you can verify is the tap happened inside the bounds of subview or not.
It seems like you just want both of those gesture recognizers to work simultaneously. Just implement UIGestureRecognizerDelegate for your parentView and make it tapGestureRecognizer's and gestureRecognizerA's delegate. Then implement an optional method there:
// MARK: - UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) {
return true
}
That might be able to detect a tap in subView even while doing a circular motion within parentView.
UPDATE: When using gesture recognizers, "forwarding touches" would be to simply calling a method of another recognizer. Just put a recognizer which is doing the forwarding as its parameter.
For instance, tapGestureRecognizer fires viewWasTapped(_ sender: UITapGestureRecognizer) when a tap is detected. Now, when your gestureRecognizerA wants to forward its events to tapGestureRecognizer, it simply does so by calling:
subView.viewWasTapped(self.gestureRecognizerA)
With an obvious change to the method itself:
func viewWasTapped(_ sender: UIGestureRecognizer) {
// ...
}
This works for UITapGestureRecognizer. The sender can be any other UIGestureRecognizer and you'd still have almost all the information to resolve a tap gesture there.
I'm trying to use a UIPageViewController for standard pagination with the Scroll transition style while having an gestures starting from the edge trigger a different action. Currently I'm trying to do this with a UIScreenEdgePanGestureRecognizer. However, no matter what I do, the UIPageViewController's gesture recognizer overrides the UIScreenEdgePanGestureRecognizer, which never gets activated. Any ideas?
To get multiple gesture recognizers to work simultaneously you have to indicate that by overriding shouldRecognizeSimultaneouslyWithGestureRecognizer from the UIGestureRecognizerProtocol:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
This example returns true for all gesture recognizers, you can limit/configure the behaviour with the passed parameters.
I've got, in a UIScrollview, multiple custom subviews which inherit from UIView and which are draggable. Everything works fine with it except that i'm able to drag two or more subviews at the same time. The gesture recognizer are attached to my custom subviews and implemented inside this class.
Is there any way to prevent this behavior ?
EDIT : I've already tried to add in the delegate
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
But it's not working since all the subviews handle themselves their own gesture recognizer.
The GestureRecognizerDelegate protocol has a function to specify whether multiple gesture recognizers can act simultaneously. I don't know if that works in your case but it is worth a try:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
I know it is an old question but I came across the same problem where I want only one item to be draggable at same time. You can loop through all your draggable subviews and update their properties as below.
subiew.isExclusiveTouch = true
subview.isMultipleTouchEnabled = false
Now only one subview will be draggable at same time.
My app has a table view (with a scroll-into of course) and this view slides on and off with a gesture recognizer (like on the Facebook app).
If I use a button to slide [the table view onto the screen], it works fine but when I use a gesture recognizer, the table view can't be scrolled anymore.
Here is the code of gesture recognizer with the problem:
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
Somebody have an idea?
Your gesture is probably preventing the scroll view gesture from working because by default only 1 gesture can be recognising at a time. Try adding yourself as the delegate of your gesture and implementing:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
self.slidingViewController.panGesture.delegate = self;
also, add <UIGestureRecognizerDelegate> to the list of protocols you implement
I have used UIPangesture in my UItableview and to avoid this gesture I have used below delegate,
//This method helped me stopped up/down pangesture of UITableviewCell and allow only vertical scroll
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
let translation = panGestureRecognizer.translationInView(superview)
if fabs(translation.x) > fabs(translation.y) {
return true
}
return false
}
return false
}
Here is the swift version:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
I had same issue of defining long press gesture on table view and not being able to scroll table when I long press on it.
Fixed by:
1- adding
UIGestureRecognizerDelegate
2- adding
gesture.delegate = self (after you defined the long press gesture)
3- adding this function:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {return true}
If I get it right the view that you're adding the gesture recognizer to is the table view. By default the UIScrollView (and implicitly UITableView) class uses the pan gesture recognizer for the scroll and your gesture recognizer interferes with that. If you use another view as a container for the table view and you're adding the pan gesture recognizer to it should work.