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.
Related
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
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;
}
I have a UIViewController where I have 2 UISwipeGestureRecognizers handling undo and redo (swipe right to undo, swiple left to redo). Within this VC I also have a UIView that is tracking touch began/moved/ended to change colors on another UIView. BTW, the undo/redo has to do with the color changes.
The problem I'm running into is that when I'm doing the touch events in the color changer view, they are sometimes interpreted as a swipe and undo/redo are happening.
How can I disable the swipe gestures just for the UIView in question but retain the ability to perform swipes on other areas of the VC?
Make the view controller a delegate of the gesture recognizer, then implement this delegate method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return touch.view != self.mySubviewToExclude;
}
I have a UIButton that has an UILongPressGestureRecognizer attached to it.
If the button is enabled I receive events from the gestureRecognizer.
However, if the button is disabled (i.e. button.enabled = NO) I don't receive those event.
Is there any way to receive events from a UILongPressGestureRecognizer if the UIButton is not enabled?
A few options:
Don't actually disable the button, just set a flag internally and don't perform the button action when the flag is false. Side effect is that the button will still look like it's working.
Create another button over top of the disabled button that has no visible appearance. Attach a Long Press to that as well. When you enable the visible button, disable the invisible button and vice versa.
Put a Long Press on the parent view use the gesture delegate to see if it's on top of your button:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view == theButton)
{
// Perform your action
}
}
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;
}