Double tapping problem - objective-c

Im working on an app with zooming function.
In this app I have this button. I want it to respond to tapping in several ways:
Single tap: Zoom in slightly.
Double tap: Zoom in to the max.
Ive tried several options to achieve this but none are what I want.
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
tapGesture.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:tapGesture];
[zoomin addTarget:self action:#selector(zoominMax) forControlEvents:UIControlEventTouchDownRepeat];
Both work on single and double tap but when I press the button once to slightly zoom and seconds later I press it again it doesn't zoom in slightly, it zooms in to the max.
It is possible to fix this with a timer and location check so that when u tap and tap again u can be sure that the location is in a similar area and the taps happened within timer range.
But is this what I really need?
Is there a simpler solution?

the solution provided by omz is not good.
where as you can do this by simply adding these lines of code like posted here. Double-tap or two single-taps?
NOTE THE MAGICAL LINE : [tapRecg requireGestureRecognizerToFail:doubleTapRecg];
ABSTRACT:
UITapGestureRecognizer *doubleTapRecg = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(doubleTapped:)];
doubleTapRecg.delegate = self;
doubleTapRecg.numberOfTapsRequired = 2;
doubleTapRecg.numberOfTouchesRequired = 1;
[view addGestureRecognizer:doubleTapRecg];
UITapGestureRecognizer *tapRecg = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(tapped:)];
tapRecg.delegate = self;
tapRecg.numberOfTapsRequired = 1;
tapRecg.numberOfTouchesRequired = 1;
[view addGestureRecognizer:tapRecg];
[tapRecg requireGestureRecognizerToFail:doubleTapRecg];
[doubleTapRecg release];
[tapRecg release];

You can do it with two gesture recognizers and a timer:
UITapGestureRecognizer *tapGestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)] autorelease];
[myView addGestureRecognizer:tapGestureRecognizer];
UITapGestureRecognizer *doubleTapGestureRecognizer = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTap:)] autorelease];
doubleTapGestureRecognizer.numberOfTapsRequired = 2;
[myView addGestureRecognizer:doubleTapGestureRecognizer];
You'll have to use a slight delay in your tap: action before zooming in slightly because the first tap could be followed by a second tap:
- (void)tap:(UITapGestureRecognizer *)recognizer
{
[self performSelector:#selector(singleTap) withObject:nil afterDelay:0.25];
}
- (void)singleTap
{
//slightly zoom in...
}
- (void)doubleTap:(UITapGestureRecognizer *)recognizer
{
//Cancel the timer for the single tap action:
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:#selector(singleTap) object:nil];
//zoom in to the max zoom level...
}

Related

Having issue with number of taps in UITapGestureRecognizer

I am trying to run a method by 2 times tapping on tv remote, consider tapping not clicking, but the touch surface does't recognize the taps. Instead, clicking two times runs the doubleTapping method.
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
doubleTap.allowedTouchTypes =#[[NSNumber numberWithInteger:UITouchTypeIndirect]];
doubleTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleTap];
- (void)handleTap:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan)
{
// handling code
NSLog(#"2 times");
}
}
I am missing something?
I was forgot to mention the UIPressType value , now due to position of remote's surface (Up / Down / Right / Left) you can now detect user's tap direction and add numberOfTapsRequired to the action :
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[tapGestureRecognizer setAllowedPressTypes:#[#(UIPressTypeLeftArrow)]];
[tapGestureRecognizer setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:tapGestureRecognizer];

tap gesture not recognized on uiimageview

I added two uiimageviews, one on another subview uiview (imageview1,imageview2). In the first view the top uiimageview is hidden(imageview2) and in the second view the bottom imageview is hidden(imageview1).
Allocating tap gesture:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneTap:)];
UITapGestureRecognizer *singleTap1 = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneTap:)];
Set user interaction for both uiimageview to YES.
[singleTap setNumberOfTapsRequired:1];
[singleTap1 setNumberOfTapsRequired:1];
// adding gesture to uiimageview
Add tap gesture recognizer and selector respectively.
[imageview1 addGestureRecognizer:singleTap];
[imageview2 addGestureRecognizer:singleTap1];
But my taps are not recognized.
Can any one tell me where the mistake is?
Try setting setUserInteractionEnabled:YES before adding gesture recognizer.
[imageview1 setUserInteractionEnabled:YES]
[imageview2 setUserInteractionEnabled:YES]
[imageview1 addGestureRecognizer:singleTap];
[imageview2 addGestureRecognizer:singleTap1];
Update:
After the comment you have made I suggest you bring your views to the top before detecting the tap event. Because parent imageView is above and catches these taps.
[yourparentview bringSubviewToFront:imageview1];
[yourparentview bringSubviewToFront:imageview2];
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(oneTap:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
singleTap.delegate = self;
[imageview1 addGestureRecogniser:singleTap];
[singleTap1 release];
imageview1.userInteractionEnabled = YES; //disabled by default

iOS - Double tap on uibutton

I have a button and I'm testing the taps on it, with one tap it change a background color, with two taps another color and with three taps another color again.
The code is:
- (IBAction) button
{
UITapGestureRecognizer *tapOnce = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnce:)];
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice:)];
UITapGestureRecognizer *tapTrice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTrice:)];
tapOnce.numberOfTapsRequired = 1;
tapTwice.numberOfTapsRequired = 2;
tapTrice.numberOfTapsRequired = 3;
//stops tapOnce from overriding tapTwice
[tapOnce requireGestureRecognizerToFail:tapTwice];
[tapTwice requireGestureRecognizerToFail:tapTrice];
//then need to add the gesture recogniser to a view - this will be the view that recognises the gesture
[self.view addGestureRecognizer:tapOnce];
[self.view addGestureRecognizer:tapTwice];
[self.view addGestureRecognizer:tapTrice];
}
- (void)tapOnce:(UIGestureRecognizer *)gesture
{
self.view.backgroundColor = [UIColor redColor];
}
- (void)tapTwice:(UIGestureRecognizer *)gesture
{
self.view.backgroundColor = [UIColor blackColor];
}
- (void)tapTrice:(UIGestureRecognizer *)gesture
{
self.view.backgroundColor = [UIColor yellowColor];
}
The problem is that the first tap don't works, the other yes.
If I use this code without button it works perfectly.
Thanks.
If you want the colors to change on tap of button, you should add these gestures on button in viewDidLoad method or so rather than on the same button action. The above code will repeatedly add gestures on tap of the button to the self.view and not on button.
- (void)viewDidLoad {
[super viewDidLoad];
UITapGestureRecognizer *tapOnce = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapOnce:)];
UITapGestureRecognizer *tapTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTwice:)];
UITapGestureRecognizer *tapTrice = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapTrice:)];
tapOnce.numberOfTapsRequired = 1;
tapTwice.numberOfTapsRequired = 2;
tapTrice.numberOfTapsRequired = 3;
//stops tapOnce from overriding tapTwice
[tapOnce requireGestureRecognizerToFail:tapTwice];
[tapTwice requireGestureRecognizerToFail:tapTrice];
//then need to add the gesture recogniser to a view - this will be the view that recognises the gesture
[self.button addGestureRecognizer:tapOnce]; //remove the other button action which calls method `button`
[self.button addGestureRecognizer:tapTwice];
[self.button addGestureRecognizer:tapTrice];
}

Why does UIPinchGestureRecognizer couldn't recive Ended state?

I have 4 gesture recognizers for 1 view.
- (void)createGestureRecognizers {
UITapGestureRecognizer *singleFingerSingleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleFingerSingleTap:)];
singleFingerSingleTap.numberOfTapsRequired = 1;
[self.panelController.view addGestureRecognizer:singleFingerSingleTap];
UITapGestureRecognizer *singleFingerDoubleTap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSingleFingerDoubleTap:)];
singleFingerDoubleTap.numberOfTapsRequired = 2;
[self.panelController.view addGestureRecognizer:singleFingerDoubleTap];
[singleFingerSingleTap requireGestureRecognizerToFail:singleFingerDoubleTap];
[singleFingerSingleTap release];
[singleFingerDoubleTap release];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePanGesture:)];
[self.panelController.view addGestureRecognizer:panGesture];
[panGesture release];
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePinchGesture:)];
[self.panelController.view addGestureRecognizer:pinchGesture];
[pinchGesture release];}
I need to process Ended state for UIPinchGestureRecognizer, but sometimes it has last state Changed, not Ended how it should be. Does anybody know why? I try to play with setDelaysTouchesEnded: but nothing :(
Pinch gesture is gesture of 2 fingers, so you sometimes one finger gets left on screen while other is already up. So, my advice is to handle UIGestureRecognizerStateCancelled and UIGestureRecognizerStateFailed as well as UIGestureRecognizerStateEnded
It's the same issue as the UIRotationGestureRecognizer, it will trigger for each movement and will stop when you stop, but it won't tell you - hey the user removed the fingers, this movement is over.
This is because it's a continuous gesture, not a simple gesture.
You should handle UIGestureRecognizerStateEnded too.

UITapGestureRecognizer on MKMapView breaks MKAnnotation selection

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);
}