How to avoid to trigger a UIPanGestureRecognizer when there is a tap on a UIButton? - ios

I have added UIPanGestureRecognizer on the view of my UIViewController.
In this view (a calculator) are some UIButton triggered by the event .TouchUpInside.
The problem comes if I tap on the button and make a small pan at the same time (which might happen if you tap quickly a button and are moving to the next one at the same time). Then the pan gesture is triggered. I would like to avoid it when there is a tap on a button. But I would like to allow it if the tap takes too long (let say 0.3s is enough to trigger the pan gesture).
How can I achieve that?

Set the property cancelsTouchesInView of your gesture recognizer to NO.
Then your button should work properly.

You can use the delegate method like this-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
if ([touch.view isKindOfClass:[UIButton class]]) {
return NO;
}
return YES;
}

There is a dirty solution. You can just grab it in a UIScrollView

Related

ios swipe after longpress is ended, without lifting the finger

I want to implement back navigation, using longpress and swipe to the left, without lifting the finger, but the swipe gesture isn't recognised, if I don't lift the finger after the longpress.
I also implemented the following delegate method, but the desired result isn't appearing. Any thoughts?
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer == _longPress && otherGestureRecognizer == _swipe) {
return YES;
}
if (gestureRecognizer == _swipe && otherGestureRecognizer == _longPress) {
return YES;
}
return NO;
edit:
- the longpress gesture fires method, which changes the background color of the current UIViewController (made it, just to see, if it fires).
-the swipe gesture fires method, -popViewController:animated
Don't use 2 different gesture recognisers because this is 1 gesture. You should create a custom gesture subclass to encode your logic so it's a single logical gesture for you to add and for the user to execute.
Inside your gesture i'd have a small state machine so you know when you start, when the long press time is up, if they have actually swiped enough. From each state you're only looking for one thing to happen, if anything else happens then you know it's a failure and the gesture can fail out.

Cancel gesture recognizer on button action

I'm working on an iPad app. I have a view in which the user can draw with his finger. This view has a subview, which is a calculator, and which have buttons.
I would like that when the user touch a button, the superview (in which the user can draw) doesn't take into account this touch. (so the user doesn't draw when he touches the calculator)
Preferably, I would like to not change the code of the calculator view and the code of my superview. I have only access to them via properties of another class.
Is there a way to solve the problem please? I have tried exclusiveTouch, but it doesn't work.
If you have access to the button action and the drawing gesture you can simply set:
gesture.enabled = NO;
To cancel the current gesture processing and / or prevent it from starting. When you want to reenable the gesture depends on what type it is and how it's used but doing it immediately (on the next line) will probably work ok.
Try this but include UIGestureRecognizerDelegate in your header file.
This is from apple "SimpleGestureRecognizers" example-
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
// Disallow recognition of tap gestures in the segmented control.
if ((touch.view == YourButton))
{
//change it to your condition
return NO;
}
return YES;
}

UILongPressGestureRecognizer and UITextField don't work together

I have a UIViewController with a LongPressGesturerecognizer attached.
There is also a UITextField in the view controllers view.
If I tap on the UITextField, the Gesturerecognizer catches the long press. Copy, paste, cursor oving is not possible.
I would like to have the Gesturerecognizer be active anywhere in the view except the UITextField, where I would like the default OS behaviour like copy, paste, move the cursor etc.
Is that possible? Can I somehow tell the gesture recognizer to forward the gesture to the UITextFields default?
You have to set a delegate to your UILongPressGestureRecognizer and implement the gestureRecognizer:shouldReceiveTouch: delegate method like this:
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return touch.view != self.textField;
}

Cancel touch on UIButton on touch move (iOS)

I have a view with button and touch-move gesture. When user touches button it becomes selected and keeps receiving touch-move events. I want to deselect the button on touch-move and pass moves to gesture.
How to cancel touch receiving on button "elegantly"?
Try the next line of code on Swift 4
youButton.touchesCancelled([], with: nil)
Works well with pan gesture reco
You need to implement the UIGestureRecognizerDelegate. Specifically this method. Then just build your logic for deciding if the gesture should receive the touch or not. If you return NO then the touch is up for grabs for the button. if you return YES the gesture to take the touch.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
If you never even more control I think you'll need to subclass the button and takeover its hit testing.

detecting finger up/down UITapGestureRecognizer

How can I know when the finger is down and when is it up with UITapGestureRecognizer?
The documentation says I should only handle UIGestureRecognizerStateEnded as tap so it means there is UIGestureRecognizerStateBegin when finger is down, but all I get is UIGestureRecognizerStateEnded.
The code I use to register the recognizer is:
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)]
UITapGestureRecognizer is a discrete gesture recognizer, and therefore never transitions to the began or changed states. From the UIGestureRecognizer Class Reference:
Discrete gestures transition from Possible to either Recognized
(UIGestureRecognizerStateRecognized) or Failed
(UIGestureRecognizerStateFailed), depending on whether they
successfully interpret the gesture or not. If the gesture recognizer
transitions to Recognized, it sends its action message to its target.
(Remembering of course that UIGestureRecognizerStateRecognized == UIGestureRecognizerStateEnded).
The docs are saying that you should check the state of a tap gesture recognizer to see that it is in its ended state, before you fire your code to say that it has been recognized. They are not saying that the tap gesture actually transitions to the began or changed states (although I admit that the docs are a little misleading in the language used!).
If you want to check for the finger down event for a tap gesture recognizer, I would recommend just using touchesBegan:withEvent:, since this is what you are really after anyway.
You could override the delegate method -(BOOL)gestureRecognizer:shouldReceiveTouch:.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
NSLog(#"Hello from press down");
return YES;
}

Resources