I have two types of recognizer, one for tap and one for swipe
UIGestureRecognizer *recognizer;
//TAP
recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(numTap1:)];
[(UITapGestureRecognizer *)recognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:recognizer];
self.tapRecognizer = (UITapGestureRecognizer *)recognizer;
recognizer.delegate = self;
[recognizer release];
//SWIPE RIGHT
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
self.swipeRightRecognizer =(UISwipeGestureRecognizer *)recognizer;
swipeRightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRightRecognizer];
self.swipeRightRecognizer = (UISwipeGestureRecognizer *)recognizer;
[recognizer release];
with this function I can disable taps on some objects.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ((touch.view == loseView) || (touch.view == subBgView) || (touch.view == btnAgain)) {
return NO;
}
return YES;
}
How can I disable swipes?
Thanks a lot!
UIGestureRecognizer has a property named enabled. This should be good enough to disable your swipes:
swipeGestureRecognizer.enabled = NO;
Edit: For Swift 5
swipeGestureRecognizer.isEnabled = false
Why don't you set the delegate for the swipe gesture recognizer too and handle them within the same delegate method.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ( [gestureRecognizer isMemberOfClass:[UITapGestureRecognizer class]] ) {
// Return NO for views that don't support Taps
} else if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] ) {
// Return NO for views that don't support Swipes
}
return YES;
}
I have a similar issue. Some of my disabled users tap and swipe at the same time, so the app moves to the next screen. I set up an option to allow them to use a three-fingered tap instead. I need to invoke the option the popoverControllerDidDismissPopover delegate and when the app first starts. So I wrote a method that combines the answers above. It looks for all of the swipe gesture recognizers and turns them off, then turns on my tap gesture recognizer.
- (void)changeGestureRecognizer {
// Three finger tap to move to next screen
if ([Globals sharedInstance].useDoubleTapToMoveToNextScreen) {
// Let’s see which gestures are active and turn off the swipes
for (UIGestureRecognizer *gestureRecognizer in self.view.gestureRecognizers) {
NSLog(#"The gestureRecognizer is %#", gestureRecognizer);
if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] ) gestureRecognizer.enabled = NO;
}
// Add the three finger tap
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeNext)];
[twoFingerTap setNumberOfTapsRequired:1];
[twoFingerTap setNumberOfTouchesRequired:3];
[self.view addGestureRecognizer:twoFingerTap];
}
}
Related
I have a UIView where i added a UITapGestureRecognizer:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
tapRecognizer.numberOfTapsRequired=1;
tapRecognizer.numberOfTouchesRequired=1;
[self.myView addGestureRecognizer:tapRecognizer];
I then add a UIToolBar with a button to the view:
UIToolbar *topBar = [[UIToolbar alloc ]initWithFrame:CGRectMake(0, 0, self.myView.frame.size.width, 44)];
topBar.barStyle = UIBarStyleBlackTranslucent;
UIBarButtonItem *logout = [[UIBarButtonItem alloc] initWithTitle:#"Logout" style:UIBarButtonItemStyleBordered target:self action:#selector(logout)];
[topBar setItems:#[logout] animated:NO];
I'm having an issue where I click on the logout button, and my tap recognier fires instead of my logout action. If I click and hold, then the logout action will fire (I'm guessing the tap recognizer is failing so lets the buttion action fire).
how can I not fire the gesture recognizer when the button is pressed?
Just had the same problem. Because I don't want to introduce container views (the UIToolbar should cover my existing view). With the help of Patrick.Ji's coarsely pointing I came up with this:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view.superview isKindOfClass:[UIToolbar class]]) {
return NO;
}
return YES;
}
Don't forget to set the delegate of the gesture to self
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *mainTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(mainTapGesture:)];
mainTapGestureRecognizer.delegate = self;
[self.view addGestureRecognizer:mainTapGestureRecognizer];
}
Check the view in your tap recognizer. If it is your logout button, let the touch fail to pass it up the chain via super.
Alternatively, make sure your toolbar is not a subview of your view. Instead, have a container view containing with your toolbar and your content view, and add the gesture recognizer to this content view.
implement this delegate method of UIGestureRecognizer (remember to set your tapRecognizer.delegate = self)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch: (UITouch *)touch {
if ([touch.view isKindOfClass:[UIBarButtonItem class]])
{
return NO;
}
return YES;
}
I've got the View-Controller with a button. I want the new view to be loaded over my View-Controller when the button is pressed. It'd not replace the existing view, I want it to be smaller than the screen and hide when I tap out of the small view.
How should it be implemented in code?
- (IBAction)button:(id)sender
{
UIView *view2=[[UIView alloc]initWithFrame:CGRectMake(0,0,200,200)];
[self.view addSubview:view2];
UITapGestureRecognizer *Tap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(Tapview)] autorelease];
[view2 addGestureRecognizer:Tap];
}
-(void)Tapview
{
[view2 removeFromSuperview];
}
Add Tap Gesture to self.view like this:
UITapGestureRecognizer *oneFinger =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneFingerAction:)] autorelease];
// Set required taps and number of touches
[oneFinger setNumberOfTapsRequired:1];
[oneFinger setNumberOfTouchesRequired:1];
// Add the gesture to the view
[[self view] addGestureRecognizer:oneFinger];
Add one BOOL flag in .h file; in ViewDidLoad method add this:
flag = FALSE;
Now I assume u have UIView *smallView which be added on screen like this:
[self.view addSubView:smallView];
flag = TRUE;
smallView.center = self.view.centre;
Now when tapped on self.view tap gesture action called
- (void)oneFingerAction:(UITapGestureRecognizer*)sender
{
if(sender.view == self.view)
{
if(flag){
if(smallView)
{
[smallView removeFromSuperView];
}
}
}
}
I had added a UILongPressGestureRecognizer to a tableview in my ViewDidLoad method. I added this to detect long press on table view in my code. But it never works. In ViewDidLoad I added this code :
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[self.resultTableView addGestureRecognizer:lpgr];
[lpgr release];
I also added this method :
-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
CGPoint p = [gestureRecognizer locationInView:self.resultTableView];
NSIndexPath *indexPath = [self.resultTableView indexPathForRowAtPoint:p];
if (indexPath == nil) {
NSLog(#"long press on table view but not on a row");
}
else {
NSLog(#"long press on table view at row %d", indexPath.row);
}
}
Please help me to resolve this?
Your code is working. I think you have to add UIGestureRecognizerDelegate delegate in .h file or how to declare resultTableView i mean you define programmatically or using .xib file.Check it once.
I have tried like this.
resultTableView = [[UITableView alloc] init];
resultTableView =[[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 420) style:UITableViewStylePlain];
resultTableView.rowHeight = 100.0;
resultTableView.delegate=self;
resultTableView.dataSource=self;
[self.view addSubview:resultTableView];
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPress:)];
lpgr.minimumPressDuration = 2.0; //seconds
lpgr.delegate = self;
[resultTableView addGestureRecognizer:lpgr];
[lpgr release];
It looks like you want to add the gesture to the individual cells, but you are adding the gesture to the table. Try adding the gesture to your UITableViewCell instead.
If the gesture recognizer is being blocked by the UITableView panGestureRecognizer, implement the delegate to ensure both can work
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
I've added a UITapGestureRecognizer to an MKMapView, like so:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(doStuff:)];
[tapGesture setCancelsTouchesInView:NO];
[tapGesture setDelaysTouchesEnded:NO];
[[self myMap] addGestureRecognizer:tapGesture];
[tapGesture release];
This almost works: tap gestures are recognized and double taps still zoom the map. Unfortunately, the UITapGestureRecognizer interferes with the selection and deselection of MKAnnotationView elements, which are also triggered by tap gestures.
Setting the setCancelsTouchesInView and setDelaysTouchesEnded properties doesn't have any effect. Annotation selection works fine if I don't add the UIGestureRecognizer.
What am I missing?
UPDATE:
As suggested by Anna Karenina below, this problem can be avoided by returning YES in the shouldRecognizeSimultaneouslyWithGestureRecognizer: delegate method.
More details in this answer.
Instead of tap gesture, add long press gesture as below :-
UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(longpressToGetLocation:)];
lpgr.minimumPressDuration = 2.0; //user must press for 2 seconds
[mapView addGestureRecognizer:lpgr];
[lpgr release];
- (void)longpressToGetLocation:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateBegan)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D location =
[self.mapView convertPoint:touchPoint toCoordinateFromView:self.mapView];
NSLog(#"Location found from Map: %f %f",location.latitude,location.longitude);
}
there is a way to delimit the swipe only on a specific item?
in this way it works everywhere
UIGestureRecognizer *recognizer;
//RIGHT
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeRight:)];
self.swipeRightRecognizer =(UISwipeGestureRecognizer *)recognizer;
swipeRightRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRightRecognizer];
self.swipeRightRecognizer = (UISwipeGestureRecognizer *)recognizer;
[recognizer release];
thanks!
You can add the swipe recognizer to only the view you want to swipe. Or, you can do this:
swipeRightRecognizer.delegate = self;
//...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch {
return (touch.view == myViewThatShouldReceiveSwipes);
}