I'm adding both a UIPanGestureRecognizer and UIPinchGestureRecognizer to the same view. This typically would not cause any issues, but the requirement for 3 fingers with my UIPanGestureRecognizer is causing problems:
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinched:)];
[self.view addGestureRecognizer:pinchGesture];
UIPanGestureRecognizer panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panning:)];
panGesture.minimumNumberOfTouches = 3;
panGesture.maximumNumberOfTouches = 3;
[self.view addGestureRecognizer:panGesture];
Occasionally, the pinch gesture will get called when the pan should have been. It works ~50% of the time, but what is a better way to implement these two gestures on the same view so the accuracy is better?
Edit: I only want one gesture to happen at a time.
Set the delegates for the gestures to self and set your ViewController to implement UIGestureRecognizerDelegate
And add this method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
other post has a typo I think, but use this
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return NO;
}
and add this so other gestures will fail before the gesture you want to start
requireGestureRecognizerToFail
Related
Please help me with the below scenario.
Self.view (Swipe Gesture added here)
UicollectionView Object in subView (Default pan,swipe gestures are there)
Want to disable scrollview scrolling/failCollectionViewPan gesture for 2 finger swipe event
Means collection view will not scroll if 2 finger swipe executed
Another approach can be to disable Collection view scrolling while 2 fingers used. Over here, I want not to swipe collection view on 2 finger swipe.
I have implemented this code, but its slowing down scrolling.
[self.collectionView.panGestureRecognizer shouldBeRequiredToFailByGestureRecognizer:_swipeL];
Then I have implemented below codes
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
return YES;
}
Now both, Swipe and Scroll are working together.
Then, I have tried in a below manner, but still not got fixed.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
if([gestureRecognizer isKindOfClass:[UISwipeGestureRecognizer class]]){
if(gestureRecognizer.numberOfTouches==2){
if( [[otherGestureRecognizer.view class] isSubclassOfClass:[UITableViewCell class]] ||
[NSStringFromClass([otherGestureRecognizer.view class]) isEqualToString:#"UITableViewCellScrollView"] ||
[NSStringFromClass([otherGestureRecognizer.view class]) isEqualToString:#"UITableViewWrapperView"] || [NSStringFromClass([otherGestureRecognizer.view class]) isEqualToString:#"UIScrollViewPanGestureRecognizer"] || [NSStringFromClass([otherGestureRecognizer.view class]) isEqualToString:#"UIScrollViewPagingSwipeGestureRecognizer"])
{
NSLog(#"Allow&Disable %#", [otherGestureRecognizer description]);
[gestureRecognizer requireGestureRecognizerToFail:otherGestureRecognizer];
return NO;
}
}
}
return YES;
}
Also I have implemented below 2 methods to fix it but fails.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer NS_AVAILABLE_IOS(7_0);
Its is able to fix for ScrollView with such ways, but the same ways are not working for UICollectionView. Because of, colection view's default pan gesture, it cannot be able to modified. While tring this way, app crashed.
If you want to detect pan gesture, try something like this. But you need to recognise direction of pan gesture:
- (void)viewDidLoad
{
[super viewDidLoad];
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(panGesture:)];
panGesture.delegate = self;
[self.yourCollectionView addGestureRecognizer:panGesture];
}
- (void)panGesture:(UIPanGestureRecognizer *)gesture;
{
if (gesture.numberOfTouches == 2) {
NSLog(#"Two fingers pan gesture");
}
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]
&& gestureRecognizer.numberOfTouches == 2) {
return NO;
}
return YES;
}
Your problem with UISwipeGestureRecognizer is, that it fires later than UIPanGesture, so in the shouldRecognizeSimultaneouslyWithGestureRecognizer delegate call, swipe gesture is always otherGestureRecognizer, and UIPanGesture is always gestureRecognizer, and in this function you can only disable otherGestureRecoginzer...
UPDATE:
Another solution: use another UIPanGestureRecognizer to disable scroll pan gesture:
- (void)viewDidLoad
{
[super viewDidLoad];
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeGesture:)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionDown;
swipeGesture.delegate = self;
swipeGesture.numberOfTouchesRequired = 2;
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:nil];
panGesture.delegate = self;
[self.tableView addGestureRecognizer:panGesture];
[self.tableView addGestureRecognizer:swipeGesture];
}
- (void)swipeGesture:(UIPanGestureRecognizer *)gesture;
{
NSLog(#"Two fingers swipe gesture");
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]]
&& gestureRecognizer.numberOfTouches == 2) {
return NO;
}
return YES;
}
This answer might be late, but I did have a similar problem today and couldn't find a solution, until I figured something out myself. It's quite simple, actually.
Swift 5
We create a gesture
let gesture = UIPanGestureRecognizer(target: self, action: #selector(functionCall))
gesture.minimumNumberOfTouches = 2
gesture.maximumNumberOfTouches = 2
We then assign that gesture to the collectionView, effectively overwriting the scroll gesture on it.
collectionView.addGestureRecognizer(gesture) // simply overwrites the 2 finger gesture on the collectionView
It now is possible to scroll the collectionView with 1, 3 or more fingers, but the 2 finger pan gesture is blocked.
I've looked around on Stack for solutions to this and found quite a few results, but I'm still unable to fix my problem, mainly because I'm working on a CCNode opposed to some UIView.
Anyways, my CCButton works find without the UITapGestureRecognizer, but when I implement it, it overrides my button press. Obviously I would like to avoid this.
My code is below. My swipe gestures work perfectly, but the tap interferes with my button. I'm not sure if I'm adding the gesture recognizer to the wrong view, because - (BOOL)gesturerecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch never runs, which is where I would put in my exception. If anyone can give me some code/ideas on how to fix this it would be greatly appreciated, thanks!
-(void)didLoadFromCCB
UITapGestureRecognizer * gridTapped = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(gridTapped)];
[[[CCDirector sharedDirector] view] addGestureRecognizer:gridTapped];
//this works totally fine
UISwipeGestureRecognizer * swipeLeft= [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(swipeLeft)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[[[CCDirector sharedDirector] view] addGestureRecognizer:swipeLeft];
}
-(void)gridTapped {
//this works!
CCLOG(#"Grid tapped");
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
//This never runs
CCLOG(#"gesture recognized");
if ((touch.view == mainMenuButton)) {
return NO;
}
return YES;
}
Try setting the UITapGestureRecognizer delegate:
gridTapped.delegate = self;
You'll need to declare the VC class as implementing <UITapGestureRecognizerDelegate>
Hello everyone I have a uitapgesture on my view using the following code :
UITapGestureRecognizer *tap= [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(TAPGestureRecognizer)];
tap.numberOfTapsRequired=1;
tap.delegate = self;
[self.view addGestureRecognizer:tap];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
And I have a uiwebview as a subview in my UIview. The problem is that on the uivewview HTML it had a onclick(); which in turn is calling the tapgesture. Any help?
FirstView.image=[UIImage imageNamed:#"shape1.jpg"];
FirstView.tag=1;
FirstView.userInteractionEnabled=YES;
[FirstView addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(firstimagetouch:)]];
SecondWebView.tag=2;
SecondWebView.userInteractionEnabled=YES;
[SecondWebView addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(firstimagetouch:)]];
-(void)firstimagetouch:(UIGestureRecognizer *)sender
{
UIView * view=sender.view;
NSLog(#"%ld",(long)view.tag);
}
try like this first add gesture recognizer to view and then your webview according to give him tag value and get tag value. and do what you want.
What I have is my view controllers view with several subviews. The hierarchy looks something like:
[view controller view]
[container view]
[view1,view2,view3,view4,view5,etc...]
[gesture view (full screen)]
I'm trying to implement pinch and 2-finger panning, but cannot get them to work simultaneously:
UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc]
initWithTarget:self action:#selector(handlePinch:)];
pinch.delegate = self;
UIPanGestureRecognizer *pullDownContainerView = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(pullingDownContainerView:)];
pullDownContainerView.minimumNumberOfTouches = 2;
pullDownContainerView.maximumNumberOfTouches = 2;
pullDownContainerView.delegate = self;
[self.touchView addGestureRecognizer:pullingDownContainerView];
[self.touchView addGestureRecognizer:pinch];
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Another strange thing is that shouldRecognizeSimultaneouslyWithGestureRecognizer isn't being called (I have implemented the UIGestureRecognizerDelegate protocol).
They do work individually. I've read something about using a scroll view where pan and pinch are readily available or something. So I'd need to replace the container view's UIView with a UIScrollView
Would like some guidance.
Update:
Did a quick clean and build and now it's working!
I have a UIView on some part of screen. This UIView has Pan gesture recognizer. This UIView ( mainVw) has a UITextView that completely covers the UIView. This UITextview has swipe gestures(left and write).
My problem is When I swipe left or right, The UIView starts dragging also. What I want is ,when I drag the UIView it should drag and when I swipe UITextView should swipe left write but no dragging.
Here is the code I'm using to give better understanding:
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[panGesture setMinimumNumberOfTouches:1];
panGesture.delegate =(id)self;
[self.mainVw addGestureRecognizer:panGesture];
//[self.mainVw.layer setValue:[NSValue valueWithCGPoint:vwCaptionBg.center] forKey:#"originalCenter"];
UISwipeGestureRecognizer *rightRecognizer;
rightRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanTouch:)];
[rightRecognizer setDirection: UISwipeGestureRecognizerDirectionRight];
rightRecognizer.delegate=(id)self;
[self.txtVw addGestureRecognizer:rightRecognizer];
UISwipeGestureRecognizer *vwLeftRecognizer;
vwLeftRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanTouch:)];
[vwLeftRecognizer setDirection: UISwipeGestureRecognizerDirectionLeft];
vwLeftRecognizer.delegate=(id)self;
[self.txtVw addGestureRecognizer:vwLeftRecognizer];
You could try using the [GESTURE requireGestureRecognizerToFail:GESTURE_TO_FAIL]; method. This would be your swipes would need to fail before the pan would be allowed to proceed.
There is also delegate methods you can use for simultaneous gestures.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
Or you could use either of these delegate methods with your own logic.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer