I'm using UIGestureRecognizer for pan, rotate, pinch. But i'm applying to whole view. I need to remove gesture for button other than subviews. But when i use pan the button also affecting. How to restrict button move from self.view. I used below code for UIPanGestureRecognizer.
UIPanGestureRecognizer *dbpan = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(ondbPan:)];
[self.view addGestureRecognizer:dbpan];
[closeButton removeGestureRecognizer:dbpan];
Pan:
- (void)ondbPan:(UIPanGestureRecognizer *)gesture
{
if ((gesture.state == UIGestureRecognizerStateChanged) ||
(gesture.state == UIGestureRecognizerStateEnded)) {
CGPoint offset = [gesture translationInView:self.view];
CGPoint center = gesture.view.center;
center.x += offset.x;
center.y += offset.y;
gesture.view.center = center;
[gesture setTranslation:CGPointZero inView:self.view];
}
}
Try with bellow code that delegate of UIGestureRecognizer return FALSE if that subview is kind of class UIButton Class. also set delegate dbpan.delegate = self; while you setting and add UIPanGestureRecognizer.
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIButton class]])
{
return FALSE;
}
else
{
return TRUE;
}
}
UPDATE:-
I dont Know why that not working at your end i test this creating one demo as well using this code:-
.h file
#interface myviewcontroller : UIViewController<UIGestureRecognizerDelegate>
and .m class
- (void)pan:(UIPanGestureRecognizer *)gesture
{
if ((gesture.state == UIGestureRecognizerStateChanged) ||
(gesture.state == UIGestureRecognizerStateEnded)) {
CGPoint location = [gesture locationInView:self.view];
[demoView setCenter:location];
}
}
- (BOOL) gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIButton class]])
{
return FALSE;
}
else
{
return TRUE;
}
}
- (void)viewDidLoad
{
UIPanGestureRecognizer *dbpan = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(pan:)];
dbpan.delegate=self;
[self.view addGestureRecognizer:dbpan];
[super viewDidLoad];
}
-(IBAction)B1called
{
NSLog(#"This is called button 1");
}
-(IBAction)B2called
{
NSLog(#"This is called button 2");
}
And it's Output is
On Swift:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (touch.view!.isKindOfClass(UIButton)) {
return false
}
return true
}
Note: Make sure UIGestureRecognizerDelegate is added and tapGesture.delegate = self on viewDidLoad().
Try this...
while (closeButton.gestureRecognizers.count) {
[closeButton removeGestureRecognizer:[closeButton.gestureRecognizers objectAtIndex:0]];
}
Related
Following is the code I have written to put 2 finger swipe on UITableView :
UISwipeGestureRecognizer *leftSwipe = [UISwipeGestureRecognizer new];
[leftSwipe addTarget:self action:#selector(nextDay)];
leftSwipe.numberOfTouchesRequired = 2;
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
leftSwipe.delegate = self;
[leftSwipe setCancelsTouchesInView:YES];
[tableViewTasks addGestureRecognizer:leftSwipe];
UISwipeGestureRecognizer *rightSwipe = [UISwipeGestureRecognizer new];
[rightSwipe addTarget:self action:#selector(previousDay)];
rightSwipe.numberOfTouchesRequired = 2;
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
rightSwipe.delegate = self;
[rightSwipe setCancelsTouchesInView:YES];
[tableViewTasks addGestureRecognizer:rightSwipe];
I am using SWTableViewCell which has left and right (single tap) gestureRecognisers.
When UITableView is swiped left/right using 2 fingers, SWTableViewCell left and right gestures are also fired after that.
How to stop the conflict ?
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if (SWTableViewCellTouch) {
SWTableViewCellTouch = NO
return NO;
}
return YES;
}
when you touch the SWTableViewCell set a BOOL SWTableViewCellTouch to YES.
The possible solution is enable/disable the BOOl (SWTableViewCellTouch) in the touchesBegan: method as below.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([[event touchesForView:self] count] > 1) {
// Its two finger touch so set the BOOL false like
SWTableViewCellTouch = NO;
}
else if ([[event touchesForView:self] count] == 1){
// Its sigle finger touch so set the BOOL true like
SWTableViewCellTouch = YES;
}
[super touchesBegan:touches withEvent:event] ;}
Hope this will help you.
1. Implement UIGestureRecognizerDelegate in your UIViewController
2. Set leftSwipe.delegate = self; and leftSwipe.delegate = self;
3. Now check if the in its Delegate Method if UISwipeGesture have how many numberOfTouchesRequired
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ( [gestureRecognizer isMemberOfClass:[UISwipeGestureRecognizer class]] ) {
UISwipeGestureRecognizer *swipeGesture=(UISwipeGestureRecognizer *)gestureRecognizer ;
if(swipeGesture.numberOfTouchesRequired!=2)
{
//if Double not Double Swipe Touch Don't Linsten Gesture in your Viewcontroller
return NO;
}
}
return YES;
}
i hope this will solve your problem
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];
}
}
From my side I will try bellow code, but it is not working.
- (void) handleTouch:(UITapGestureRecognizer *) gesture
{
CGPoint touchPoint = [gesture locationInView:self.view];
NSArray *viewsAtPoint = [self viewsAtPoint:touchPoint];
for(TheifView * aView in viewsAtPoint)
{
[aView removeFromSuperview];
}
}
- (void) registerGesture
{
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTouch:)];
tapGesture.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapGesture];
}
Gesture target and selector can be removed by following code
[gesture removeTarget:self action:#selector(handleTouch:)];
Put tag to ThiefView...say 111. and then u can identify it and remove from self.view. If this is not the answer you expected then explain with clear description..
//For Removing Gestures from View..
for (UIGestureRecognizer *recognizer in self.view.gestureRecognizers) {
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]) {
[self.view removeGestureRecognizer:recognizer];
}
}
//For Removing ThiefView from View
for (UIView *subview in self.view.subviews) {
if (subview.tag==111) {
[subview removeFromSuperview];
}
}
To remove it fully
- (void) handleTouch:(UITapGestureRecognizer *) gesture
{
[self.view removeGestureRecognizer:gesture];
}
To remove its target
- (void) handleTouch:(UITapGestureRecognizer *) gesture
{
[gesture removeTarget:self action:#selector(handleTouch:)];
}
To disable the gesture
- (void) handleTouch:(UITapGestureRecognizer *) gesture
{
gesture.enabled=NO;
}
I have a UIScrollView as a subview in another UIScrollView I am trying to prevent scrolling from occurring in the subview and pass the touch to the superview.
- (void)viewDidLoad
{
self.outerScrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
self.outerScrollView.showsVerticalScrollIndicator = NO;
self.gestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
self.gestureRecognizer.delegate = self;
[self.tableViewController.tableView addGestureRecognizer:self.gestureRecognizer];
[self.outerScrollView addSubview:self.tableViewController.tableView];
[self.view addSubview:self.outerScrollView];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
if (gesture.state == UIGestureRecognizerStateBegan) {
if (gesture.view == self.tableViewController.tableView) {
self.tableViewController.tableView.contentOffset = CGPointMake(0, 0);
// Pass to self.outerScrollView
// Trying to make self.outerScrollView take over the touch
}
}
}
I have a gesture recognizer on my view controller which I use to slide in/out the navigation bar. Unfortunately there is a bad NSZombie that makes the whole app crash when I go swipe to go to the previous controller. It's very difficult to track because it only happens in a specific view controller.
Here is the error:
[MyViewController gestureRecognizer:shouldBeRequiredToFailByGestureRecognizer:]: message sent to deallocated instance
And here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UIPanGestureRecognizer *pgr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pgr:)];
pgr.delegate = self;
[self.view addGestureRecognizer:pgr];
}
- (void)pgr:(UIPanGestureRecognizer *)gesture {
// Check if this is the first touch
if (gesture.state == UIGestureRecognizerStateBegan) {
CGPoint point = [gesture locationInView:gesture.view];
self.start = point.y;
}
CGPoint point = [gesture locationInView:gesture.view];
self.currentX = point.x;
self.offsetY = point.y - self.start;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if ([gestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
return YES;
}
return NO;
}
The delegate method is
- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Try to use
- (BOOL)shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([otherGestureRecognizer isKindOfClass:[UIScreenEdgePanGestureRecognizer class]]) {
return YES;
}
return NO;
}