I am adding a UITapGestureRecognizer to my application to detect a double tap gesture.
UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(handleTapGesture:)];
tapgr.numberOfTaps = 2;
tapgr.delegate = self;
[_view addGestureRecognizer:tapgr];
[tapgr release];
This is working fine unless I show a tooltip in my application. They are set up like this:
[_view.toolTipView addTarget:self action:#selector(handleTap:) forControlEvents:UIControlEventTouchUpInside];
Before the introduction of my gesture recognizer, these tooltips where clickable and reacted, now they aren't reacting anymore...
How can I make a gesture recognizer and a standard UIControlEventTouchUpInside-Setup work together?
I found a solution:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (gestureRecognizer == tapgr) {
return ![touch.view isKindOfClass:[UIControl class]];
}
return YES;
}
This method prevents the GestureRecognizer from being fired when a UIControl (i.e. Button) is pressed.
if you want the _view can respond single tap and Double tap together, you can try this
UITapGestureRecognizer * singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
UITapGestureRecognizer * doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleTap setNumberOfTapsRequired:2];
//Add this code to disable double tap and only responds to single tap when user tap the _view just once time
[singleTap requireGestureRecognizerToFail:doubleTap];
[self addGestureRecognizer:doubleTap];
[self addGestureRecognizer:singleTap];
[singleTap release];
[doubleTap release];
if you want to use TouchEvent try UIControlEventTouchDownRepeat
[button addTarget:self actionselector(multipleTap:withEvent:) forControlEvents:UIControlEventTouchDownRepeat];
//Try to check wheather is doulbe tap or single tap.
-(IBAction)multipleTap:(id)sender withEvent:(UIEvent*)event {
UITouch* touch = [[event allTouches] anyObject];
if (touch.tapCount == 2) {
// do action.
}
}
You can't do that. I think you should choose another way to implement that.
Related
I am working on an application which works like a remote control of different devices like Game Console, Set-top Box, etc.
Application contains different type of controls like gesture and buttons to perform events as remote.
Single gesture view contains multiple gesture recognizer as follow:
1 finger Tap using UITapGestureRecognizer
2 finger Tap using UITapGestureRecognizer
1 finger swipe using UISwipeGestureRecognizer
2 finger swipe using UISwipeGestureRecognizer
My requirement is to implement 1 finger Swipe gesture recognizer along with hold event. So, that will continue my swipe action until user will not remove its finger from the view.
I have tried UILongPressGestureRecognizer after UISwipeGestureRecognizer but this didn’t work for me because it is executing along with Swipe movement. And I want this after Swipe end, but finger will not remove.
My code snippet :
-(void) gestureView:(UIView*)viewGesture {
UISwipeGestureRecognizer *swipeGestureSingleRight;
UISwipeGestureRecognizer *swipeGestureSingleLeft;
UISwipeGestureRecognizer *swipeGestureSingleUp;
UISwipeGestureRecognizer *swipeGestureSingleDown;
swipeGestureSingleUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleUp setDelegate:self];
[swipeGestureSingleUp setDirection:(UISwipeGestureRecognizerDirectionUp)];
[swipeGestureSingleUp setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleUp];
swipeGestureSingleDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleDown setDelegate:self];
[swipeGestureSingleDown setDirection:(UISwipeGestureRecognizerDirectionDown)];
[swipeGestureSingleDown setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleDown];
swipeGestureSingleRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleRight setDelegate:self];
[swipeGestureSingleRight setDirection:(UISwipeGestureRecognizerDirectionRight)];
[swipeGestureSingleRight setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleRight];
swipeGestureSingleLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGestureSingle_Handle:)];
[swipeGestureSingleLeft setDelegate:self];
[swipeGestureSingleLeft setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[swipeGestureSingleLeft setNumberOfTouchesRequired:1];
[viewGesture addGestureRecognizer:swipeGestureSingleLeft];
longPressGestureOnSwipe = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(longPressGesture_Handle:)];
longPressGestureOnSwipe.minimumPressDuration = 0.03;
longPressGestureOnSwipe.delegate = self;
[viewGesture addGestureRecognizer:longPressGestureOnSwipe];
isSwipeEnd = false;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
- (void)swipeGestureSingle_Handle:(UISwipeGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
singleTouchSwipeSenderDirection = sender.direction;
isSwipeEnd = true;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
}
-(void)longPressGesture_Handle:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
isSwipeEnd = false;
[longPressGestureOnSwipe setEnabled:isSwipeEnd];
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
if (isSwipeEnd) {
[super touchesBegan:touches withEvent:event];
} else {
return;
}
}
Please suggest me correction or solution for my requirement.
Thanks in advance!
I am trying to use this code for a tap gesture recognizer, it works fine when number of taps required is set to 2, but when I set the number of taps required to 1 it stop functioning. I appreciate any help in getting this to work.
UITapGestureRecognizer *doubleTap =
[[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(tapDetected:)];
[doubleTap setNumberOfTapsRequired : 1];
[doubleTap setDelaysTouchesBegan : YES];
[self.view addGestureRecognizer:doubleTap];
You try this:-
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(tapDetected:)];
singleTap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:singleTap];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(tapDetected:)];
doubleTap.numberOfTapsRequired = 2;
[self.view addGestureRecognizer:doubleTap];
[singleTap requireGestureRecognizerToFail:doubleTap];
This works for me.
If You only want the receiver to respond to one/first touch then setDelaysTouchesBegan:NO Since this is used for processing touches in UITouchPhaseBegan so it is analyzed and is prevented from being delivered. Property discussion from documentation:
When the value of this property is NO (the default), views analyze touch events in UITouchPhaseBegan and UITouchPhaseMoved in parallel with the receiver. When the value of the property is YES, the window suspends delivery of touch objects in the UITouchPhaseBegan phase to the view. If the gesture recognizer subsequently recognizes its gesture, these touch objects are discarded. If the gesture recognizer, however, does not recognize its gesture, the window delivers these objects to the view in a touchesBegan:withEvent: message (and possibly a follow-up touchesMoved:withEvent: message to inform it of the touches’ current locations). Set this property to YES to prevent views from processing any touches in the UITouchPhaseBegan phase that may be recognized as part of this gesture.
It looks to me like you are simply failing to set the delegate of your GestureRecognizer. Are you sure the double tap was firing successfully? When I placed your code into my project I see the same behavior but setting the delegate properly and using shouldRecognizeSimultaneouslyWithGestureRecognizer causes it to recognize the single tap properly.
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapDetected:)];
[doubleTap setDelegate:self];
[doubleTap setNumberOfTapsRequired : 1];
[doubleTap setDelaysTouchesBegan : YES];
[picker addGestureRecognizer:doubleTap];
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isKindOfClass:UITapGestureRecognizer.class] &&
[otherGestureRecognizer isKindOfClass:UITapGestureRecognizer.class])
{
return YES;
}
else
{
return NO;
}
}
I have a UIView and a tap gesture recognizer in it:
UIImageView *tabView = [[UIImageView alloc] initWithFrame:CGRectMake(41, 145, 702, 100)];
tabView.image = [UIImage imageNamed:#"inactive_tab"];
tabView.userInteractionEnabled = YES;
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleSingleTap:)];
[tabView addGestureRecognizer:singleFingerTap];
[self.scrollView addSubview:tabView];
And I add another view on scrollview:
[self.scrollView addSubview:self.activeTab];
activeTab is over the inactiveTap. When I tap to activeTap, gesture recognizer fires, whis I dont want to be happened. How can I avoid this?
Use UIGestureRecognizerDelegate and its method gestureRecognizer:shouldReceiveTouch:.
You can check if the touch point is inside a view frame and return NO if you don't want the touch to happen on that view.`
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint touchLocation = [touch locationInView:self.view];
return !CGRectContainsPoint(self.activeTab.frame, touchLocation);
}
I am trying to add 2 gestures to a uiimage that pulls a subVIew. One gesture is swipe to open/close. And the other is longpressand hold to open it at a specific height.
longPress.minimumPressDuration = 1;
[imageNavigationSlider addGestureRecognizer:longPress];
UILongPressGestureRecognizer *longPressWall = [[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handleLongPressWall:)] autorelease];
longPressWall.minimumPressDuration = 1;
PullMeImage.userInteractionEnabled=YES;
[PullMeImage addGestureRecognizer:longPressWall];
UISwipeGestureRecognizer *swipe = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipe:)] autorelease];
swipe.direction = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight;
[PullMeImage addGestureRecognizer:swipe];
[swipe setDelegate:self];
The long press gesture is correctly recognized, but the swipe isn't.
I also tried using:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
But with no success. Any help will be very much appreciated.
Thank you
I have several IBActions attached to UIButtons. The IBActions work fine until I add the following code:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"View Did Load");
[self addGestureRecognizersToView:drawImage];
}
After I add that chunk of code the IBActions do not fire. The UIButtons highlight when I touch them, but none of the IBAction code gets hit.
Here is my addGestureRecognizers code:
- (void)addGestureRecognizersToView:(UIImageView *)theView {
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[panGesture setMaximumNumberOfTouches:2];
[panGesture setMinimumNumberOfTouches:1];
//panGesture.delegate = drawImage;
[theView addGestureRecognizer:panGesture];
[panGesture release];
UITapGestureRecognizer *doubleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[doubleFingerTap setNumberOfTapsRequired:2];
[self.view addGestureRecognizer:doubleFingerTap];
[doubleFingerTap release];
UITapGestureRecognizer *singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[singleFingerTap setNumberOfTapsRequired:1];
[self.view addGestureRecognizer:singleFingerTap];
[singleFingerTap release];
}
If I comment out the singleFingerTap code it works. I'm guessing I should not be using alloc since I have already alloced that once before in doubleFingerTap?
Any ideas on what I might be missing here?
You single finger tap is hindering with the normal behavior of the button. You will have to make sure the touches get through unhindered.
[singleFingerTap setCancelsTouchesInView:NO];
It sounds like the UITapGestureRecognizer is intercepting the taps that would otherwise have been handled by the UIButtons.
You can use gestureRecognizer:shouldReceiveTouch::
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return (touch.view != self.button1 &&
touch.view != self.button2);
}
Alternatively, you could hack the responder chain.