UIView *superview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
UIView *subview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
UIPanGestureRecognizer *recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget: self action: #selector(handlePinch);
superview.userInteractionEnabled = YES;
subview.userInteractionEnabled = YES;
[superview addGestureRecognizer:recognizer];
I have a subview overlapping on top of a superview. The subview has 4 buttons that needs to be tappable. The superview has a pinch-zoom gesture that zooms the view. But i would like to disable the zoom on the subview.
The recognizer is fired inside the subview as well, is there a way to exclude the recognizer from the subview?
I used the simple way below:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view != subview) { // accept only touchs on superview, not accept touchs on subviews
return NO;
}
return YES;
}
UIView *superview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
superview.tag=1; //set Tag for superview
UIView *subview = [[UIView alloc] initWithFrame:CGRectMake:(0, 0, 320, 480);
subview.tag==2; //set Tag for subview
UIPanGestureRecognizer *recognizer = [[UIPinchGestureRecognizer alloc] initWithTarget: self action: #selector(handlePinch);
superview.userInteractionEnabled = YES;
subview.userInteractionEnabled = YES;
[superview addGestureRecognizer:recognizer];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
if(touch.view .tag==2) //if subview is touched then disable pinch gesture.
{
return NO;
}
return YES;
}
This might not be the best option, but this could also work? Other StackOverflow users please be kind, I'm new!
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
CGPoint touchPoint = [gestureRecognizer locationInView: superview];
if(CGRectContainsPoint(subview.frame, touchPoint)
{
return NO;
}
return YES;
}
Apple Docs containing CGRectContainsPoint.
https://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CGGeometry/index.html#//apple_ref/c/func/CGRectContainsPoint
Related
I have two view. One is transparent view which contains subviews. I want to remove screenView only when parent view is clicked. I don't want to call tapGesture when i click popUpView. How to can check?
screenView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
screenView.backgroundColor = [UIColor clearColor];
UITapGestureRecognizer * clearTable = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(clearTableViewAction:)];
[clearTable setNumberOfTapsRequired:1];
[screenView setUserInteractionEnabled:YES];
[screenView addGestureRecognizer:clearTable];
screenView.tag = 100;
[self.view addSubview:screenView];
self.popUpView = [[UIView alloc]init];
self.popUpView.frame = ...
self.popUpView.backgroundColor = WhiteColor;
self.popUpView.userInteractionEnabled = YES;
self.popUpView.tag = 200;
[screenView addSubview:self.popUpView];
-(void)clearTableViewAction:(UITapGestureRecognizer*)sender {
if(sender.view.tag == 100){
[UIView animateWithDuration:0.2
animations:^{screenView.alpha = 0.0;}
completion:^(BOOL finished){ [screenView removeFromSuperview];
}];
}
}
Use shouldReceiveTouch delegate method and check:
Like,
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view.tag == 100)
{
return YES;
}
else
{
return NO;
}
}
Now, clearTableViewAction gesture method will not be called if you will click in popUpView.
I'm trying to add UITableView inside UIView but I got problem with gesture recognizer. This is my code:
_subView = [[UIView alloc] initWithFrame:CGRectMake(0, screenRect.size.height-100, screenRect.size.width, 300)];
_subView.backgroundColor = [UIColor colorWithRed:0.110f green:0.192f blue:0.298f alpha:1.00f];
[self.view addSubview:_subView];
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(subViewToggle)];
[_subView addGestureRecognizer:singleFingerTap];
_moreTable = [[UITableView alloc] initWithFrame:CGRectMake(0,50, screenRect.size.width, 240)];
//Transforme to HOR scroll ;
CGRect frame = _moreTable.frame;
_moreTable.transform = CGAffineTransformRotate(CGAffineTransformIdentity, k90DegreesCounterClockwiseAngle);
_moreTable.frame = frame;
[_moreTable registerNib:[UINib nibWithNibName:#"MoreTableViewCell" bundle:nil] forCellReuseIdentifier:#"moreCell"];
_moreTable.backgroundColor = [UIColor groupTableViewBackgroundColor];
_moreTable.delegate = self;
_moreTable.dataSource = self;
[_subView addSubview:_moreTable];
[_subView bringSubviewToFront:_moreTable];
The problem is when I click on table cell instead of executing didSelectRowAtIndexPath method he execute the subViewToggle Method. I tried to bring my tableView to front but didn't help
your tap gesture eat the touch. there are two way you can deal:
first, you can implement - gestureRecognizer:shouldReceiveTouch: delegate method, and decide if tap gesture should occur.
second, you also can set cancelsTouchesInView property of tap to NO, so tableView will receive touch. but tap will receive touch at the some time too.
Try implementing the UIGestureRecognizerDelegate protocol's gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
This should call both your didSelectRow and GestureRecognizer
https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UIGestureRecognizerDelegate_Protocol/index.html#//apple_ref/occ/intfm/UIGestureRecognizerDelegate/gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:
Please try to use like this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view == _moreTable]) {
return NO;
}
return YES;
}
To solve this Problem I've changed the UIView Gesture from single finger tap to moveUP and moveDown gesture.
Note that I've tried only #dharmbir Solution and It haven't worked for me.
Update Also this solution, implementing the shouldReciveTouches, worked for the tapGesture and her's the code snippet :
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// UITableViewCellContentView => UITableViewCell
if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
// UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
return NO;
}
return YES;
}
//Create tap gesture for menu transparent view
UITapGestureRecognizer *rightTableTransparentViewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(rightTableTransparentViewTapMethod:)];
[rightTableTransparentViewTap setCancelsTouchesInView:NO];
[_rightTableTransparentView addGestureRecognizer:rightTableTransparentViewTap];
- (void)rightTableTransparentViewTapMethod:(UITapGestureRecognizer *)recognizer {
//Write your code here
}
I have been trying to add a UITapGestureRecognizer in order to make it possible to change views using buttons inside my UIPageViewControllerDataSource.
I have added the subclasses
#interface OverallViewController : UIViewController <UIPageViewControllerDataSource,UIGestureRecognizerDelegate>
#property (strong, nonatomic) UIPageViewController *pageController;
Page navigation works fine for me but when trying the following UITapGestureRecognizer inside viewDidLoad I get nothing
UIView *topbar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 52)];
topbar.backgroundColor = [UIColor colorWithRed:(245/255.0) green:(245/255.0) blue:(245/255.0) alpha:1];
left = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"nav-profile-sm.png"]];
left.frame = CGRectMake(15, 15, 25, 25);
//End add top nav
[topbar addSubview:left];
[self.view addSubview:topbar];
//Add top navigation gestures
UITapGestureRecognizer *profiletap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(profileButtonTap)];
profiletap.numberOfTapsRequired = 1;
profiletap.delegate = self;
[left addGestureRecognizer:profiletap];
No response here
-(void) profileButtonTap {
NSLog(#"Profile button tapped");
}
And nothing when I try overriding gestureRecognizer
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
CGPoint touchPoint = [touch locationInView:touch.view];
NSLog(#"Touch: %f,%f", touchPoint.x, touchPoint.y);
if (touchPoint.y < 52) {
return NO; // ignore the touch
}
return YES; // handle the touch
}
When I say that I get nothing I mean that nothing is logged, the methods do not seem to be called and I am unsure how I can solve or debug this further. Thanks for any help, ideas and suggestions!
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 couple of UIScrollViews in my view controller. I want to overlay a view that captures a 2 finger swipe via UIPanGestureRecognizer which will not record the UIScrollView swipe gestures.
When I put a transparent view over my content with a 2 finger pan gesture, my taps and 1 finger swipes are not detected. I tried overwriting the pointInside: method to return NO
but then it doesn't record my 2 finger swipe.
The effect is similar to the 4 finger swipe to change apps.
You don't need an overlay view.
First implement UIPanGestureRecognizer that will handle 2 finger pan and assign it to your view that contains UIScrollViews
UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc]
initWithTarget:self
action:#selector(handlePan:)];
panGestureRecognizer.delegate = self;
panGestureRecognizer.minimumNumberOfTouches = 2;
panGestureRecognizer.maximumNumberOfTouches = 2;
[self.view addGestureRecognizer:panGestureRecognizer];
Use UIGestureRecognizerDelegate to handle 2 finger pan with UIScrollView pan gesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
And finally you are able to handle 2 fingers pan
- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer
{
NSLog(#"pan");
}
If you want to stop scrolling UIScrollView when two finger pan is detected you can disable and enable UIScrollView pan recognizers
- (void)handlePan:(UIPanGestureRecognizer *)gestureRecognizer
{
if(gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
_scrollView.panGestureRecognizer.enabled = NO;
}
if(gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
_scrollView.panGestureRecognizer.enabled = YES;
}
NSLog(#"pan");
}
If you don't really need the overlay you can solve this with just gesture recognizers. I wrote this up as a test:
- (void)viewDidLoad {
[super viewDidLoad];
self.scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds];
_scrollView.contentSize = CGSizeMake(self.view.bounds.size.width * 2, self.view.bounds.size.height);
UIView *green = [[UIView alloc] initWithFrame:self.view.bounds];
[green setBackgroundColor:[UIColor greenColor]];
UIView *blue = [[UIView alloc] initWithFrame:CGRectOffset(self.view.bounds, self.view.bounds.size.width, 0)];
[blue setBackgroundColor:[UIColor blueColor]];
[_scrollView addSubview:green];
[_scrollView addSubview:blue];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(twoFingerPan:)];
[pan setMinimumNumberOfTouches:2];
[pan setMaximumNumberOfTouches:2];
[pan setDelaysTouchesBegan:YES];
[_scrollView addGestureRecognizer:pan];
[self.view addSubview:_scrollView];
}
- (void)twoFingerPan:(UIPanGestureRecognizer *)gesture {
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
self.scrollView.scrollEnabled = NO;
break;
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateFailed:
self.scrollView.scrollEnabled = YES;
break;
default:
break;
}
NSLog(#"2 Fingers!");
}
I get the twoFingerPan: call back for when 2 fingers are used. The scroll view's panGestureRecognizer is still working at that point so I disable scrolling on the scroll view to handle the 2 finger pan. I've found this method work's pretty well. One sort of wonky thing is if the scroll view is decelerating the 2 finger gesture recognizer isn't called. Hope that helps!