I am using UISwipeGestureRecognizer for left and right direction swipe in my main view as follow:
UISwipeGestureRecognizer *recognizer1,*recognizer;
recognizer1 = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFromleft:)];
[recognizer1 setDirection:(UISwipeGestureRecognizerDirectionLeft)];
[self.view addGestureRecognizer:recognizer1];
[recognizer1 release];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFromright:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[self.view addGestureRecognizer:recognizer];
[recognizer release];
and in this same view I am also using touch event like touch begin,move and end.
Both are used for different purpose.
My problem is that when I touch my view and moving it from left to right or right to left;
UISwipeGestureRecognizer is called in between the touch began and touch moved method which i dont want
so anyone know how can i avoid this type of thing?
how can i tell the view that i am now want to use touch event or i am using UISwipeGestureRecognition
Take a look at reference there is a property called cancelsTouchesInView. So the way I see it is to determine if you want to handle the gesture or standard touch in swipeHandlers, and set the cancelsTouchesInView property accordingly
Related
I have added the following gesture recognizers to a view:
UIPinchGestureRecognizer *pch= [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(ViewPinching:)];
[[self view] addGestureRecognizer:pch];
// and
UIPanGestureRecognizer *d = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(ViewDragging:)];
[d setMinimumNumberOfTouches:4];
[[self view] addGestureRecognizer:d];
I want to fire the event when 4 fingers are dragged and when I do that the Pinch gesture recognizer fires instead of the Pan gesture recognizer. I was thinking that maybe I could fix this problem if I restrict the UIPinchGestureRecognizer to be fired only if touches.count=2
edit
I don't know if this will be practical or not. Maybe I could add:
UIPinchGestureRecognizer *pch= [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(ViewPinching:)];
[[self view] addGestureRecognizer:pch];
every time touches start if there is two touches I will add that event and remove it ontouchesended.
This is ultimately a bad idea. A 4-finger pinch in iOS 5 will close your app, and a 4 finger pan will switch to the next app (obviously not good for UX). If you absolutely must use 4 fingers, make a subclass of UIGestureRecognizer and do the pinching logic yourself. Let me apologize ahead of time for not having an example, as your use case is quite unique.
Previously, I asked about how to capture any touch input on an MPMoviePlayerController's view when the MPMovieControlStyle is set to MPMovieControlStyleNone. It was suggested that I could use a UIGestureRecognizer to do this.
I am able to capture double taps on the screen using a gesture recognizer in this manner, but not single taps. The code I used for this is as follows:
///**********///
singleTapGestureRecognizer =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleClickOnMediaView:)];
singleTapGestureRecognizer.numberOfTapsRequired = 1;
[self.moviePlayer.view addGestureRecognizer:singleTapGestureRecognizer];
[singleTapGestureRecognizer release];
///**********///
Why am I unable to capture single taps on an MPMoviePlayerController's view using this code? Is there something special about how it handles single taps?
I know it's a bit old question, but here's a solution, if anyone needs this.
To handle single and double taps on the same view, the single tap recognizer has to wait for the double tap recognizer to fail. Something like this:
UITapGestureRecognizer* doubleTapRecon = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap)];
[doubleTapRecon setNumberOfTapsRequired:2];
[doubleTapRecon setDelegate:self];
[self.view addGestureRecognizer:doubleTapRecon];
UITapGestureRecognizer* singleTapRecon = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap)];
[singleTapRecon setNumberOfTapsRequired:1];
[singleTapRecon requireGestureRecognizerToFail:doubleTapRecon];
[singleTapRecon setDelegate:self];
[self.view addGestureRecognizer:singleTapRecon];
Note, that if you are not using ARC, you have to take care of memory managment.
No the above answer will not work to get single tap gesture you have to implement 'UITapGestureRecognizerDelegate' and use the method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Because 'moviePlayer' is also using tap gesture, so to get working our custom single Tap Only above method is required.
I have a parent view called ImageViewController. To this view I add up to two subviews called ImageDetailViewController. In this detail view controller I declare a few gestures that need to do certain things on their respective views only. Here is the code:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(changeModeButtonPushed:)];
[tap setNumberOfTapsRequired:2];
[tap setNumberOfTouchesRequired:1];
[tap setDelegate:self];
[openGLView addGestureRecognizer:tap];
[tap release];
UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(touchDidDrag:)];
[panRecognizer setMaximumNumberOfTouches:1];
[openGLView addGestureRecognizer:panRecognizer];
[panRecognizer release];
UIPanGestureRecognizer *shiftRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(shiftView:)];
[shiftRecognizer setMinimumNumberOfTouches:2];
[openGLView addGestureRecognizer:shiftRecognizer];
[shiftRecognizer release];
UIPinchGestureRecognizer *pinchRecog = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(viewPinched:)];
[openGLView addGestureRecognizer:pinchRecog];
[pinchRecog release];
So I need to have two of these detail views load up next to each other inside of this parent view, and then I need to be able to do these gestures on one view or the other, and have that view respond.
The problem is that when I 1 finger pan around with 1 finger, sometimes it will call on the view it is supposed to, but most often, it fires on the other view! It doesn't make any sense! I have tried debugging and everything else I can think of, but I just can't see how two separately declared objects can get mixed up like this.
To make things stranger, there are some gestures that do work correctly. So it's only this one finger pan around gesture that screws everything up.
What could I be missing? How can I even debug this? Everything is looking like the objects are indeed separate, but they just aren't behaving that way...
You could debug/solve this by finding out what view your gesture recogniser is calling on: Have a look at this code:
(void)NAMEOFFUNCTION:(UITapGestureRecognizer*)recognizer {
if ([yourViewController.view pointInside:[recognizer locationInView:presentationSlideViewController.view] withEvent:nil]) {
}
filter through all your subviews, in this example i'm checking to see if the finger touch is below a defined x and then y coordinate. First check to see if the point is inside the _buttonVIew subview://
if ([_buttonView pointInside:[recognizer locationInView:_buttonView] withEvent:nil]) {
Then check to see if the touch is in a coordinate lower than 50
if (([recognizer locationInView:_buttonView].x < 50) && ([_leftArrow isEnabled])) {
pageIndex -= 1;
}
//otheriwse check to see if its over 970
else if (([recognizer locationInView:_buttonView].x > 970) && ([_rightArrow isEnabled])) {
pageIndex += 1;
}
[self scrollViewScrollToRect:pageIndex];
[self fadeArrows:1.0];
return;
}
}
Right now I have some very simple code setup to recognize gestures. However, when my device has VoiceOver enabled and I try to use the double-tap gesture feature (to pass the gesture through voiceOver into the app), it doesn't seem to recognize the gesture.
To clarify more:
Normally, if you are using an app with voiceover enabled and the app has some gesture recognition, you can double-tap and hold for a second and voiceover will play a tone. You can then perform the gesture and it will be passed through voiceover into the app. My problem is that when I double-tap and hold, voiceover doesn't play the tone.
So I am wondering if there is something I have to include in my code to notify voiceover that my app will be using gesture, or something to that effect.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
// Swipe Left
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSwipeLeft:)];
swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeft];
[swipeLeft release];
// Swipe Right
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc]
initWithTarget:self action:#selector(handleSwipeRight:)];
swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:swipeRight];
[swipeRight release];
}
- (void)handleSwipeLeft:(UISwipeGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:self.view];
NSLog(#"Swipe left started at (%f,%f)",location.x,location.y);
UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, #"Swipe Left");
}
- (void)handleSwipeRight:(UISwipeGestureRecognizer *)recognizer
{
CGPoint location = [recognizer locationInView:self.view];
NSLog(#"Swipe right started at (%f,%f)",location.x,location.y);
}
I noticed that VoiceOver doesn't play the tone when volume is muted. Any chance that's what you're experiencing? The functionality of receiving the gesture is still there.
I have a UIView inside of a UIScrollView, both created using IB. The UIView scrolls horizontally inside the UIScrollView. I want to detect left and right 2 finger swipes.
Borrowing from the sample code I found in SmpleGestureRecognizers, I have put the following code in the viewDidLoad method of the UIScrollView's ViewController...
UIGestureRecognizer *recognizer;
UISwipeGestureRecognizer *swipeRightRecognizer, *swipeLeftRecognizer;
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
swipeRightRecognizer = (UISwipeGestureRecognizer *)recognizer;
swipeRightRecognizer.numberOfTouchesRequired = 2;
[self.view addGestureRecognizer:swipeRightRecognizer];
[recognizer release];
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
swipeLeftRecognizer = (UISwipeGestureRecognizer *)recognizer;
swipeLeftRecognizer.numberOfTouchesRequired = 2;
swipeLeftRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:swipeLeftRecognizer];
[recognizer release];
I have set in the viewcontroller.h. and have the following delegate method...
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
I am assuming this is a valid gestureRecognizer delegate method, but I cannot find any reference to it in the documentation.
I do not get any errors but nothing happens when I do a 2 finger swipe. The delegate method is not called and neither is my action method. I tried removing the numbeOfTouchesRequired call to see if it might work with a single finger swipe to no avail.
Am I adding the gestureRecognizers to the right view? I tried adding it to the UIView, the UIScrollView as well as self.view.superView.
The sample code runs great. The only difference I can see between my implementation of the code and the sample code is the fact that I used IB to create the views and the sample code did not. I suspect that something is consuming the swipe gesture before it gets to my recognizers.
What am I doing wrong.
Thanks,
John
I had the same problem and I solved by using UIPanGestureRecognizer instead of UISwipeGestureRecognizer.
To emulate the detection of swipe, we'll play with the speed of gesture in scrollview.
If the speed of x direction >= 3000 (for example) the swipe will be detected.
If x>0 it will be a right swipe.
The code I implemented to resolve your situation is:
In a uiscrollview named _scroll1:
UIPanGestureRecognizer *pan;
pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(Swipe4ScrollViews:)];
[pan setMinimumNumberOfTouches:2];
[_scroll1 addGestureRecognizer:pan];
[pan release];
With a global BOOL variable named _panning, Swipe4ScrollViews will do the hard job:
-(void)Swipe4ScrollViews:(UIPanGestureRecognizer *)sender
{
if(sender.state == UIGestureRecognizerStateBegan) _panning = NO;
CGPoint v =[sender velocityInView:_scroll1];
NSLog(#"%f, %f",v.x,v.y);
if( (abs(v.x) >= UMBRAL) && !_panning)
{
_panning = YES;
[sender cancelsTouchesInView];
if(v.x>0) NSLog(#"Right");
else NSLog(#"Left");
[self doSomething];
}
}
I encapsulated it on a UIGestureRecognizer subclass: UISwipe4ScrollGestureRecognizer
The biggest difference between the sample code and your code is that your code involves a UIScrollView.
Internally, scroll views, table views, and web views all use gesture recognizers to some degree. If you're expecting to receive gestures within those views – gestures that are similar to the ones already supported internally – they will almost certainly be consumed or significantly delayed before you can get to them. Receiving gestures outside or above those views should work fine, if your use case supports it.
Try setting the delayContentTouches-property of the UIScrollView to NO, maybe it'll help.