limit UIPinchGestureRecognizer to work with exactly two fingers only - ios

I have found no way in the documentation on how to specify the number of touches for UIPinchGestureRecognizer or UIRotationGestureRecognizer.
All I found anywhere is that it only works with two fingers, but by my experiments, it also works with 3 or even more fingers.
Furthermore in the action the property numberOfTouches also never returns the actual number of fingers.
I want to limit it only for two fingers because it gets all confused with other 3-finger recognizers.
Could you, please, suggest me a good way to do that? Thanks.

According to the docs UIPinchGestureRecognizer handles
[...] pinching gestures involving two touches [...]
Apparently it only considers two touches but allows additional touches to happen concurrently.
To answer your question: you can try to get the actual number of touches by other means and prevent the pinch action when that count is larger than 2. One way is to add more gesture recognizers which handle gestures on the same view (e.g. multiple UITapGestureRecognizers, one for each possible number of touches); another one is to override touchesBegan and touchesMoved of the view your gesture recognizer is installed on and use the count of the provided touches array.
(I'd go with the second approach first because managing multiple gesture recognizers in parallel can get problematic.)

Add a delegate to the pinch gesture recogniser you're concerned about.
Implement gestureRecognizer(_:, shouldRecognizeSimultaneouslyWith:) and return false if you want the pinch gesture to be ignored if there is another recogniser also in progress.

Related

Pass tap events to superview but handle long press

I'm trying to pass tap events to the superview but handle longpress events. I've added LongPressGestureRecognizer to the top view but the tap events aren't passed to the superview. I tried multiple approaches:
Overriding hitTest doesn't work since the longpress gesture recognizer handler doesn't get called
isUserInteractionEnabled - same as above
Overriding touchesBegan/Ended and calling them manually on the superview doesn't trigger the tap event
Handing complex tap interactions can be hard, and mixing different approaches can make it much much harder.
Generally, the best way to handle it is to have a single view that has multiple gesture recognisers on them. Implement the UIGestureRecognizerDelegate method gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:) and gestureRecognizer(_:shouldRequireFailureOf:) to handle conflicts. When a touch event is recognised it can delegate the action to whatever other object needs to deal with it. Having different views all trying to deal with touches at the same time is not a good way to deal with the problem. Gestures are dependent on other gestures and cannot all be handled independently by different views.

Accurate start position for UIPanGestureRecognizer?

I am using a UIPanGestureRecogniser to implement drag and drop. When the drag starts I need to identify the object that is being dragged. However the objects are relatively small. And if the user doesn't hit the object right in the centre of the object it isn't getting dragged.
The problem is that when the gesture handler is first called with the state UIGestureRecognizerStateBegan, the finger has already moved several pixels, and so [UIPanGestureRecognizer locationInView:] returns that point, which is not where the gesture truly started. That makes sense as it can only recognize a pan after a few pixels of movement. However, I need the absolute start of the gesture, not the position after the gesture has first been recognized.
I'm thinking that maybe I need to implement a tap gesture recognizer as well, purely to capture the first touch. But that seems like a hack for what is not an unusual requirement. Is there no other way of getting that first touch from within the pan gesture recognizer?
UIGestureRecognizerDelegate protocol provides methods gestureRecognizerShouldBegin: and gestureRecognizer:shouldReceiveTouch: that can help you evaluate the touches before the pan has transitioned to state UIPanGestureRecognizerStateBegan

Slide Effect for iOS

I'm new to developing iOS apps,
I've successfully implemented a Swipe Gesture Recognizer,
What I was wondering is if there is an easy to use recognizer like the swipe gesture. That would let you implement the homescreen page turning effect but just on a small view in the view controller?
If your unclear on what effect I mean, when you look at the iPhone's homescreen you can drag your finger and it responds instantly (unlike swipe) and also has some spring feeling to it, is this some effect I can use, or do I manually have to program this into the code if so is there a tutorial that explains this?
Thanks,
I hope my question makes sense.
Have a look at UIPanGestureRecognizer:
https://developer.apple.com/library/ios/documentation/uikit/reference/UIPanGestureRecognizer_Class/Reference/Reference.html
UIPanGestureRecognizer is a concrete subclass of UIGestureRecognizer
that looks for panning (dragging) gestures. The user must be pressing
one or more fingers on a view while they pan it. Clients implementing
the action method for this gesture recognizer can ask it for the
current translation and velocity of the gesture.
A panning gesture is continuous. It begins
(UIGestureRecognizerStateBegan) when the minimum number of fingers
allowed (minimumNumberOfTouches) has moved enough to be considered a
pan. It changes (UIGestureRecognizerStateChanged) when a finger moves
while at least the minimum number of fingers are pressed down. It ends
(UIGestureRecognizerStateEnded) when all fingers are lifted.
Clients of this class can, in their action methods, query the
UIPanGestureRecognizer object for the current translation of the
gesture (translationInView:) and the velocity of the translation
(velocityInView:). They can specify the view whose coordinate system
should be used for the translation and velocity values. Clients may
also reset the translation to a desired value.
Edit: The spring feeling part you would need to implement yourself. Since iOS 7 there is UIDynamics which contains different animators, for what you describe you may need UIGravityBehavior and maybe UICollisionBehaviour. Look at the WWDC 2013 videos for this topic, I think you will find some examples there.

UIGestureRecognizer Method Clarification

Hi any one can explain me, what are the cases can i use the following UIGestureRecognizer Methods.
1. - (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer*)preventingGestureRecognizer
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
2. - (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer
3. - (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
- (BOOL)shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
Kindly give the use case of all this three methods, if u have any example kindly comment here.
Thanks in advance.
Please read the Apple's Documentation.
canBePreventedByGestureRecognizer:
Overridden to indicate that the specified gesture recognizer can prevent the receiver from recognizing a gesture.
canPreventGestureRecognizer:
Overridden to indicate that the receiver can prevent the specified gesture recognizer from recognizing its gesture.
requireGestureRecognizerToFail:
Creates a dependency relationship between the receiver and another gesture recognizer.
shouldBeRequiredToFailByGestureRecognizer:
Overridden to indicate that the receiver should be required to fail by the specified gesture recognizer.
shouldRequireFailureOfGestureRecognizer:
Overridden to indicate that the receiver requires the specified gesture recognizer to fail.
All those methods simply establish dependancies of different types between different recognizers. Certain gesture recognizers may use similar gestures, and these are typically set up so that one takes precedence over another.
For example, a scrolling gesture and a swipe gesture are similar in that they both involve a touch moving in a particular direction, so you might set up the swipe recognizer such that it requires the scrolling recognizer to fail before the swipe can be recognized. Or, you could set them up so that the scrolling recognizer prevents the swipe recognizer from being activated while the user is scrolling.

How to differentiate between user swipe and tap action?

I am developing a app in which I have a view which contains subView in it.
I want to track both swipe and tap actions such as a single click.
Actions should be tracked only when the user touches within my subview. When the user taps I want to perform one action, when the user swipes I want perform another.
For tracking the swipe, I implemented UIGestureRecognizer and it is working fine. But I don't know how to track the tap option. Please guide me how to achieve this.
The main thing is, when I tap it should call tap action only and vice versa.
You can use UITapGestureRecognizer for tap gestures.
"UITapGestureRecognizer is a concrete subclass of UIGestureRecognizer
that looks for single or multiple taps. For the gesture to be
recognized, the specified number of fingers must tap the view a
specified number of times."
This method includes the numberOfTapsRequired ("The number of taps for the gesture to be recognized.") and numberOfTouchesRequired ("The number of fingers required to tap for the gesture to be recognized") properties where you can set exactly how you want it to react to user action.
In this case, as you only want it to be activated when tapped once, the default settings for both these properties (both have default values of 1) should be fine.
The best place to get the information is Defining How Gesture Recognizers Interact of Event Handling Guide for iOS
When a view has multiple gesture recognizers attached to it, you may
want to alter how the competing gesture recognizers receive and
analyze touch events. By default, there is no set order for which
gesture recognizers receive a touch first, and for this reason touches
can be passed to gesture recognizers in a different order each time.
You can override this default behavior to:
Specify that one gesture recognizer should analyze a touch before another gesture recognizer.
Allow two gesture recognizers to operate simultaneously.
Prevent a gesture recognizer from analyzing a touch.

Resources