Allow both single tap gesture recognizer and double tap in UIScrollView - ios

So I have an UIImageView inside of a UIScrollView, I need to capture both:
- single tap gesture
- double tap gesture
for the UIImageView
The double tap gesture is supposed to be sent to the UIScrollView as an action of zooming
The single tap gesture is captured by a UITapGestureRecognizer that I created myself.
The double tap gesture has higher priority than the single tap (when there is a double tap, zoom in the scrollview, else perform the single tap)
So far if I add the single tap gesture recognizer to the scrollview, the single tap is immediately recognized and no double tap can be recognized.
If I add the single tap gesture recognizer to the imageview, it never receives any action, but double tap works
Any suggestion is appreciated, thanks..

try this code,
Objective - C
UITapGestureRecognizer *singletap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(singleTap:)];
singletap.numberOfTapsRequired = 1;
singletap.numberOfTouchesRequired = 1;
[scrollView addGestureRecognizer:singletap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(doubleTap:)];
doubleTap.numberOfTapsRequired =2 ;
doubleTap.numberOfTouchesRequired = 1;
[scrollView addGestureRecognizer:doubleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
Swift 3.0
var singletap = UITapGestureRecognizer(target: self, action: #selector(self.singleTap))
singletap.numberOfTapsRequired = 1
singletap.numberOfTouchesRequired = 1
scrollView.addGestureRecognizer(singletap)
var doubleTap = UITapGestureRecognizer(target: self, action: #selector(self.doubleTap))
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
scrollView.addGestureRecognizer(doubleTap)
singleTap.require(toFail: doubleTap)

UITapGestureRecognizer *tapRecognizerForSingleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapAction:)];
[tapRecognizerForSingleTap setNumberOfTapsRequired:1];
UITapGestureRecognizer *tapRecognizerForDoubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTapAction:)];
[tapRecognizerForDoubleTap setNumberOfTapsRequired:2];
Both are added in a same image view and to achieve what you want just add the below line.
[tapRecognizerForSingleTap requireGestureRecognizerToFail:tapRecognizerForDoubleTap];
By the above line you are asking for single tap will be only recognise if it's not double tap.

Related

how can check that which uiimageview is presently clicked?

I have three UIImageview. I set the action for UIImageview by using tapGesture. I want each UIImageview to have a different action. How can I check that which UIImageview is presently clicked?
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTap setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTap];
[_imageTwo addGestureRecognizer:singleTap];
[_imageThree addGestureRecognizer:singleTap];
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
}
You can detect using below code:
-(void)singleTapping:(UITapGestureRecognizer *) recognizer{
if (recognizer.view == _imageOne){
} else if (recognizer.view == _imageTwo) {
}else
{
}
}
A UIGestureRecognizer is to be used with a single view. There is this explicit information in the Apple documentation:
Gesture Recognizers Are Attached to a View
Every gesture recognizer is associated with one view. By contrast, a
view can have multiple gesture recognizers, because a single view
might respond to many different gestures. For a gesture recognizer to
recognize touches that occur in a particular view, you must attach the
gesture recognizer to that view.
Firstly, you can't attach same UITapGestureRecognizer to more than one view.
So, your code will not work and you have to create three UITapGestureRecognizer instances and have to attach it to views like below:
UITapGestureRecognizer *singleTapImg1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg1 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg2 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg2 setNumberOfTapsRequired:1];
UITapGestureRecognizer *singleTapImg3 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapping:)];
[singleTapImg3 setNumberOfTapsRequired:1];
[_imageOne addGestureRecognizer:singleTapImg1];
[_imageTwo addGestureRecognizer:singleTapImg2];
[_imageThree addGestureRecognizer:singleTapImg3];
Now, you can use below code to get, which imageview clicked and perform action according to that:
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
if (recognizer.view == _imageOne){
//_imageOne tapped
}
else if (recognizer.view == _imageTwo) {
//_imageTwo tapped
}else{
//_imageThree tapped
}
}

Setting conditions on number of Tap gesture in ios

I have a UILabel and when i double tap on it ,it should assign value of Label to the other view's UITextView otherwise next view's textview should be empty.
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapped:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setDelegate:self];
[holderView addGestureRecognizer:tapRecognizer];
tapRecognizer = nil;
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(LaunchText)];
[doubleTapRecognizer setNumberOfTapsRequired:2];
[doubleTapRecognizer setDelegate:self];
[holderView addGestureRecognizer:doubleTapRecognizer];
holderView.userInteractionEnabled=YES;
[tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
/*n=[SingleTon getInstance];
n.Name=textLabel.text;*/
if (doubleTapRecognizer.numberOfTapsRequired==2) {
n.Name=#"hi";
}
/* if (doubleTapRecognizer.numberOfTapsRequired==2) {
n.Name=textLabel.text;
}*/
else{
//n.Name=textLabel.text;
n.Name=#"hellow";
}
-(void) LaunchText
{
[self performSegueWithIdentifier:#"textAdd" sender:self];
}
I am always getting if condition, else part never runs, What is the issue with my code?
Please try below code.
//first add single tap
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleT:)];
[tapRecognizer setNumberOfTapsRequired:1];
[holderView addGestureRecognizer:tapRecognizer];
//now add double tap
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleT:)];
[doubleTapRecognizer setNumberOfTapsRequired:2];
[holderView addGestureRecognizer:doubleTapRecognizer];
holderView.userInteractionEnabled=YES;
[tapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
Now Implement Single Tap and Double Tap Method
-(void)singleT:(UITapGestureRecognizer *)gest
{
NSLog(#"Single");
}
-(void)doubleT:(UITapGestureRecognizer *)gest
{
NSLog(#"double");
}
Maybe this will help you.
doubleTapRecognizer.numberOfTapsRequired==2 is the value you set to how many times the user has to tap to set off the gesture recognizer. it you want to allow for single and double taps you can keep a count on the gesture recognizer target and see how many times they've tapped over a giving time, like 0.2 secs or whatever time you want. I'm not 100% sure but you could also try to add two gestures to the label one for numberOfTapsRequired = 1 and numberOfTapsRequired = 2 and have them both perform different functions. Again i'm not sure on the two recognizers but you could give it a try and try the other method otherwise.

Get Coordinates of view on which longpressGesture recogniser is added

I have added longpressGesture recognizer on view & given NoofTouchesRequired=2.I want to get the coordinates of both the views on which i have longpressed.
MyCode is as below:-
//---long press gesture---
UILongPressGestureRecognizer *longpressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector (handleLongpressGesture:)];
longpressGesture.minimumPressDuration = 4;
longpressGesture.numberOfTouchesRequired = 2;
[viewLongPress addGestureRecognizer:longpressGesture];
[longpressGesture release];
UIGestureRecognizer has a locationInView: method just for that.
-(void)handleLongpressGesture:(UIGestureRecognizer *)reco{
UIView *theSuperview = self.view;
CGPoint touchPointInSuperview = [reco locationInView:theSuperview];
}

iOS UITapGestureRecognizer multiple taps

I have a UITapGestureRecognizer added to my UITextView. I have set the numberOfTapsRequired to 1, but I really need this to be ANY. aField is a UITextView. I need any number of taps to call the selector. Any way to do this?
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(stateFieldSelected)];
singleTap.numberOfTapsRequired = 1;
[aField addGestureRecognizer:singleTap];
The purpose is, I am launching a UIPickerView when they tap the State field, but if they double or triple tap the state field, it will pull up the keyboard. I could add many gesture recognizers, but it seems lame to have to do that.
There isn't anything wrong with using multiple gesture recognizers on a view. But if you're worried about the single tap action being called twice in addition to the double tap action you could specify that the single tap recognizer requires the double tap recognizer to fail:
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(someOtherMethod)];
[doubleTap setNumberOfTapsRequired:2];
[aField addGestureRecognizer:doubleTap];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(stateFieldSelected)];
[singleTap setNumberOfTapsRequired:1];
[singleTap requireGestureRecognizerToFail:doubleTap];
[aField addGestureRecognizer:singleTap];

UITapGestureRecognizer - single tap and double tap

I am trying to add 2 UITapGestureRecognizers to a view, one for single tap and one for double tap events. The single tap recognizer is working as expected (on its own). But I don't seem to be able to get the double tap recognizer working.
Have tried to experiment with properties like : cancelsTouchesInView, delaysTouchesBegan and delaysTouchesEnded but still doesn't work.
When I double tap, the single tap recognizer would always be activated and the double tap event would also be sent to the super view. But the custom double tap recognizer does not seem to be notified at all.
Documentations seem to suggest that the 3 properties mentioned above could be used for the purpose. But I am just not sure what values should be set and on which recognizer(s) (single, double or both). Hope somebody familiar with this could help.
The following is the latest updated code block.
// ****** gesture recognizers ******
- (void)addSingleAndDoubleTapGestureRecognizersToView:(UIView *)view
{
// single tap
UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: #selector(handleSingleTapOnView:)];
[singleTapRecognizer setNumberOfTouchesRequired:1];
[view addGestureRecognizer: singleTapRecognizer];
// double tap
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget: tableViewController action: #selector (handleDoubleTapOnView:)];
[doubleTapRecognizer setNumberOfTouchesRequired:2];
[singleTapRecognizer requireGestureRecognizerToFail: doubleTapRecognizer];
[view addGestureRecognizer: doubleTapRecognizer];
}
- (void)handleSingleTapOnView:(id)sender
{
}
- (void)handleDoubleTapOnView:(id)sender
{
}
UITapGestureRecognizer *singleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doSingleTap)] autorelease];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];
UITapGestureRecognizer *doubleTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doDoubleTap)] autorelease];
doubleTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
Note: If you are using numberOfTouchesRequired it has to be .numberOfTouchesRequired = 1;
For Swift
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didPressPartButton))
singleTapGesture.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTapGesture)
let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)
singleTapGesture.require(toFail: doubleTapGesture)
Swift 3 solution:
let singleTap = UITapGestureRecognizer(target: self, action:#selector(self.singleTapAction(_:)))
singleTap.numberOfTapsRequired = 1
view.addGestureRecognizer(singleTap)
let doubleTap = UITapGestureRecognizer(target: self, action:#selector(self.doubleTapAction(_:)))
doubleTap.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTap)
singleTap.require(toFail: doubleTap)
In the code line singleTap.require(toFail: doubleTap) we are forcing the single tap to wait and ensure that the tap event is not a double tap.
You need to use the requireGestureRecognizerToFail: method. Something like this:
[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
//----firstly you have to alloc the double and single tap gesture-------//
UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleDoubleTap:)];
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleSingleTap:)];
[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];
//-----------------------number of tap----------------//
[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];
//------- add double tap and single tap gesture on the view or button--------//
[self.view addGestureRecognizer : doubleTap];
[self.view addGestureRecognizer : singleTap];
Not sure if that's exactly what are you looking for, but I did single/double taps without gesture recognizers. I'm using it in a UITableView, so I used that code in the didSelectRowAtIndexPath method
tapCount++;
switch (tapCount)
{
case 1: //single tap
[self performSelector:#selector(singleTap:) withObject: indexPath afterDelay: 0.2];
break;
case 2: //double tap
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(singleTap:) object:indexPath];
[self performSelector:#selector(doubleTap:) withObject: indexPath];
break;
default:
break;
}
if (tapCount>2) tapCount=0;
Methods singleTap and doubleTap are just void with NSIndexPath as a parameter:
- (void)singleTap:(NSIndexPath *)indexPath {
//do your stuff for a single tap
}
- (void)doubleTap:(NSIndexPath *)indexPath {
//do your stuff for a double tap
}
Hope it helps
Solution for Swift 2:
let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
singleTapGesture.numberOfTapsRequired = 1 // Optional for single tap
view.addGestureRecognizer(singleTapGesture)
let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTapGesture.numberOfTapsRequired = 2
view.addGestureRecognizer(doubleTapGesture)
singleTapGesture.requireGestureRecognizerToFail(doubleTapGesture)
I implemented UIGestureRecognizerDelegate methods to detect both singleTap and doubleTap.
Just do this .
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleDoubleTapGesture:)];
[doubleTap setDelegate:self];
doubleTap.numberOfTapsRequired = 2;
[self.headerView addGestureRecognizer:doubleTap];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(handleSingleTapGesture:)];
singleTap.numberOfTapsRequired = 1;
[singleTap setDelegate:self];
[doubleTap setDelaysTouchesBegan:YES];
[singleTap setDelaysTouchesBegan:YES];
[singleTap requireGestureRecognizerToFail:doubleTap];
[self.headerView addGestureRecognizer:singleTap];
Then implement these delegate methods.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
Some view have there own double tap recognizers built in (MKMapView being an example). To get around this you will need to implement UIGestureRecognizerDelegate method shouldRecognizeSimultaneouslyWithGestureRecognizer and return YES:
First implement your double and single recognizers:
// setup gesture recognizers
UITapGestureRecognizer* singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(mapViewTapped:)];
singleTapRecognizer.delegate = self;
singleTapRecognizer.numberOfTapsRequired = 1;
UITapGestureRecognizer* doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(mapViewDoubleTapped:)];
doubleTapRecognizer.delegate = self; // this allows
doubleTapRecognizer.numberOfTapsRequired = 2;
[singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
And then implement:
#pragma mark UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer { return YES; }
In reference to #stanley's comment -
Don't try and use tap gestures to row selections to work in UITableView as it already has full tap handling....
But you must set 'Cancels Touches in View' to 'NO' on your single tap gesture recognizers or it will never get the tap events.

Resources