how to add UITapGestureRecognizer to presentViewController and to view - ios

I need to dismiss the presentViewController when click the outside the controller, I'm using the following code
UITapGestureRecognizer *tapBehindGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapBehindDetected:)];
[tapBehindGesture setNumberOfTapsRequired:1];
[tapBehindGesture setCancelsTouchesInView:NO];
[self.view.window addGestureRecognizer:tapBehindGesture];
- (void)tapBehindDetected:(UITapGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateEnded)
{
CGPoint location = [sender locationInView:nil]; //Passing nil gives us coordinates in the window
//Then we convert the tap's location into the local view's coordinate system, and test to see if it's in or outside. If outside, dismiss the view.
if (![self.view pointInside:[self.view convertPoint:location fromView:self.view.window] withEvent:nil])
{
// Remove the recognizer first so it's view.window is valid.
[self.view.window removeGestureRecognizer:sender];
[self dismissViewControllerAnimated:YES completion:nil];
}
}
}
its working fine for me, but i had problem in another view. Inside the view controller I add UITapGestureRecognizer to vwHeaderview.
UITapGestureRecognizer *addNewContactsingleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[vwHeaderview addGestureRecognizer:addNewContactsingleFingerTap];
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer
{
//Some code
}
If I click the vwHeaderview It call the "tapBehindDetected", I wont call "handleSingleTap".
If I comment above "tapBehindGesture" Its working fine. But I need both to work. any help

I add delegate to vwHeaderview and use following function & its working fine for me...
UITapGestureRecognizer *addNewContactsingleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
addNewContactsingleFingerTap.delegate = self;
[vwHeaderview addGestureRecognizer:addNewContactsingleFingerTap];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}

Related

Tap Gesture subview touch detect

i am creating drawer
self.isShowMenuVC = NO;
_menuView = [MenuViewController viewController];
[self.menuView setDelegate:self];
[self addChildViewController:self.menuView];
[self.menuView.view setFrame:CGRectMake(-kMenuTableWidth, 0, kMenuTableWidth, self.view.frame.size.height)];
[self.view addSubview:self.menuView.view];
[self.menuView didMoveToParentViewController:self];
UITapGestureRecognizer *outsideTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(outsideTapped:)];
[self.view addGestureRecognizer:outsideTap];
outsideTap.delegate = self;
and when button tap i just set frame of _menuView.view to behave like a drawer
what i want is to detect touch outside of drawer but i am not able to do it
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (touch.view == self.menuView.view) {
NSLog(#"Touch Drawer");
} else {
NSLog(#"Touch Outside");
}
return YES;
}
but it is always show Touch Outside"
i am missing something but don't know what thanks in advance
Also try with 2 gesture but not working because one gesture in self.view so, when i tap in drawer method call 2 times.
for that i tried to disable one gesture, still calling two times
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (gestureRecognizer == self.touchInDrawer) {
NSLog(#"Touch in drawer");
[self.touchOutSideDrawer setEnabled:NO];
} else {
NSLog(#"Outside");
[self hideMenuView];
}
return YES;
}
The UITapGestureRecognizer cannot detect the touch outside the view which it belongs to.
You need to create another UITapGestureRecognizer and add them to self.menuView.view.
Also you can make two #property for your gesture recognizers and check them inside method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if (gestureRecognizer == self.firstGesture) {
NSLog(#"Touch in first gesture");
} else {
NSLog(#"Touch in another gesture");
}
I have solve this issue with adding two gesture
#property (strong,nonatomic) UITapGestureRecognizer *touchInDrawer;
#property (strong,nonatomic) UITapGestureRecognizer *touchOutSideDrawer;
as per #Eugene Zaychenko's Answer but there is still problem because delegate method calling two times
also i can't [self.touchOutSideDrawer setEnabled:NO]; when touch in drawer tapped, because after that it will remove from the view and never executed again if [self.touchOutSideDrawer setEnabled:YES];
but most interesting thing is
_touchInDrawer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(outsideTapped:)];
[self.menuView.view addGestureRecognizer:self.touchInDrawer];
self.touchInDrawer.delegate = self;
_touchOutSideDrawer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(outsideTapped:)];
[self.view addGestureRecognizer:self.touchOutSideDrawer];
self.touchOutSideDrawer.delegate = self;
outsideTapped method calling only one time so i shifted my all code there and is working
- (void) outsideTapped:(UITapGestureRecognizer *)gestureRecognizer {
if (gestureRecognizer == self.touchOutSideDrawer) {
// [self.view removeGestureRecognizer:self.touchOutSideDrawer];
[self hideMenuView];
NSLog(#"Outside");
} else {
NSLog(#"Touch in drawer");
// [self.touchOutSideDrawer setEnabled:NO];
}
}

UITableViewCell is accepting only longpress

Facing trouble with UITableViewCell.I tried to get the data of selected UITableViewCell. Initially it is working good but after the UITapGestureRecognizer its making this trouble. The table i've used is assigned to the one subview even few buttons are not taking the action at first click. I am facing this trouble exactly after adding the UITapGestureRecognizer.
tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(didTapAnywhere:)];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
[self.view addGestureRecognizer:tapRecognizer];
[self.scrolling addGestureRecognizer:tapRecognizer];
[self.notesView addGestureRecognizer:tapRecognizer];
-(void)didTapAnywhere: (UITapGestureRecognizer*) recognizer {
[ageview removeFromSuperview];
[contiView removeFromSuperview];
[CountryTableview removeFromSuperview];
[notesView endEditing:YES];
[self.view endEditing:YES];
}
Your Tap Guesture is cancelling the touch guesture to your cell and your Buttons, make sure that the view to which you are assigning a tap guesture does not overlap the buttons which would result in cancellation of touch events
Did you implement delegate method of UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
UIView *view = (UIView *)touch.view;
if([view isKindOfClass:[<YOUR_BUTTON> class]]) {
return NO;
}
return YES;
}
OR you can give some tag to button like following
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
UIView *view = (UIView *)touch.view;
if(view.tag == 10000) {
return NO;
}
return YES;
}

iOS6 bug in UITapGestureRecognizer gestureRecognizer:shouldReceiveTouch:?

The following code in my view controller results in an EXC_BAD_ACCESS at the touch.view call:
- (BOOL)handleSingleTap:(UITapGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) { // <<<< EXC_BAD_ACCESS HERE
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
[self.view endEditing:YES]; // dismiss the keyboard
return YES; // handle the touch
}
touch appears to be a zombie. Specifically, touch is set to an address, and the debugger thinks that's a UITouch pointer, but it doesn't have any properties:
This did not happen in iOS 4.x. So iOS 6 bug or my fault?
The gesture recognizer is set up as follows (in the ViewController):
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:shouldReceiveTouch:)];
[tapRecognizer setDelegate:self];
[tapRecognizer setNumberOfTapsRequired:1];
[tapRecognizer setNumberOfTouchesRequired:1];
tapRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
UPDATE/SOLUTION:
Thanks to Rob for pointing out the user error on my part. Not only that, but I don't actually need the TapRecognizer since I just want to know a touch happened.
Here's the correct code to dismiss the on-screen keyboard with a touch anywhere but in a UIControl:
In the ViewController's viewDidLoad:
UIGestureRecognizer *myRecognizer = [[UIGestureRecognizer alloc] init];
[myRecognizer setDelegate:self];
myRecognizer.cancelsTouchesInView = NO;
[self.view addGestureRecognizer:myRecognizer];
[myRecognizer release];
And:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([touch.view isKindOfClass:[UIControl class]]) {
// we touched a button, slider, or other UIControl
return NO; // ignore the touch
}
[self.view endEditing:YES]; // dismiss the keyboard
return YES; // handle the touch
}
You're using a method, handleSingleTap:shouldReceiveTouch:, whose signature does not conform to the permissible signatures. See the Overview section of UIGestureRecognizer Class Reference. It should only have the one parameter, the gesture recognizer.
I think you may be confusing the handler with the UIGestureRecognizerDelegate protocol method gestureRecognizer:shouldReceiveTouch:.

How to disable UISwipeGestureRecognizer when load a new view?

in my viewDidLoad I set
UISwipeGestureRecognizer *swipeRecognizerU = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeUpDetected:)]; swipeRecognizerU.direction = UISwipeGestureRecognizerDirectionUp; [self.view addGestureRecognizer:swipeRecognizerU];
when I load a new view through popup I need to disable that gesture
// show popup view
-(IBAction)showPopup:(id)sender
{
MJDetailViewController *detailViewController = [[MJDetailViewController alloc] initWithNibName:#"MJDetailViewController" bundle:nil];
[self presentPopupViewController:detailViewController animationType:MJPopupViewAnimationSlideBottomBottom];
}
after popup view is dismissed, I need to set swipe gesture back.
// hide popup view
-(IBAction)hidePopup:(id)sender
{
[self dismissPopupViewControllerWithanimationType:MJPopupViewAnimationSlideBottomBottom];
}
how this can be done?
I think there is property named enabled for UIGestureRecognizer. Have you try this, it should be ok to disable your swipes:
swipeGestureRecognizer.enabled = NO;
You need set delegate at here.
Ex :
swipeleft=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeleft:)];
swipeleft.direction=UISwipeGestureRecognizerDirectionLeft;
swipeleft.delegate = self;
[self.view addGestureRecognizer:swipeleft];
Then add function
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ((touch.view == test[1]) || (touch.view == test[2]) || (touch.view == test[3])) {
[gestureRecognizer setCancelsTouchesInView:YES];
[swipeleft setCancelsTouchesInView:YES];
[gestureRecognizer setEnabled:NO];
[swipeleft setEnabled:NO];
return NO;
}
else
{
[gestureRecognizer setCancelsTouchesInView:NO];
[swipeleft setCancelsTouchesInView:NO];
[gestureRecognizer setEnabled:YES];
[swipeleft setEnabled:YES];
return YES;
}
}
I think useful for you

IBAction does not fire when I add viewDidLoad

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.

Resources