Is there any such thing as a generic handler for any sort of touch event? A method that get called when any sort of interaction occurs with information about the touch event passed as a parameter.
You are going to want to adhere to the UIGestureRecognizerDelegate protocol, namely the following two methods:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
Within these methods you can check the gesture recognizer object to see if it is the type of gesture you are looking for and specify whether or not the gesture should begin or receive the touch.
EDIT: To detect the end of a gesture you would have something like this:
// in viewDidLoad or in initialization of your view controller:
_panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGestureRecognizer:)];
[self addGestureRecognizer:_panGestureRecognizer];
[_panGestureRecognizer setDelegate:self];
- (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)gesture {
UIGestureRecognizerState state = [gesture state];
if (state == UIGestureRecognizerStateEnded) {
// gesture ended here
}
}
Related
I am setting up my app to be compatible with Voice Over feature. I have a graph, I am getting single tap on the -accessibilitiHint(). I need to confirm the user action on double tap which the even can be obtained with accessibilityActivate(). The touch point needs to be retrieved on Single tap.
Now Is there any method to to get user touch point when single tap is performed on my View ?
For Objective C
Step 1:Add TapeGesture Recognizer to your View
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureHandler:)];
tapGesture.delegate = self;
[yourView addGestureRecognizer:tapGesture];
Step 2: implement Gesture Delegate Method
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
Step 3: implement Gesture Handler
- (void)tapGestureHandler:(UITapGestureRecognizer *)gesture
{
CGPoint touchPoint = [gesture locationInView:yourView];
}
I made gesture like this:
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(tapOnPhoto:)];
tapGesture.numberOfTapsRequired = 1;
tapGesture.numberOfTouchesRequired = 1;
tapGesture.delegate = self;
[self.htmlWebView addGestureRecognizer:tapGesture];
And when tap on htmlWebView call gestureRecognizerShouldBegin for several time.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){
[self performSelector:#selector(tapOnPhoto:) withObject:gestureRecognizer];
}
return YES;
}
Why is gestureRecognizerShouldBegin called more than once per gesture?
As per the
gestureRecognizerShouldBegin description.
This method is called when a gesture recognizer attempts to transition
out of the UIGestureRecognizerStatePossible state. Returning NO causes
the gesture recognizer to transition to the
UIGestureRecognizerStateFailed state.
This method will get called multiple times to get the transition state of gesture.
Also as you have added a selector for TapGesture why are you calling that method explicitly, the method will get called itself.
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]){
[self performSelector:#selector(tapOnPhoto:) withObject:gestureRecognizer];
}
return YES;
}
There will be no need of this function you can remove it as you are calling only a method there.
As #Rajat mentioned in his answer you can remove the delegate method and instead use your tapOnPhoto: method to parse your gesture logic.
The UIGestureRecognizer object that you'll receive as the argument into that method has a property called state
Which might have the following values:
UIGestureRecognizerStatePossible
UIGestureRecognizerStateBegan
UIGestureRecognizerStateChanged
UIGestureRecognizerStateEnded
UIGestureRecognizerStateCancelled
UIGestureRecognizerStateFailed
UIGestureRecognizerStateRecognized
You can use a switchand provide specific logic for each case.
I googled several other questions and tutorials but couldn't find an answer for my question. I want to detect if the user has touched/tapped/hold/clicked the screen. I tried with touchesBegan: withEvent: but it is not firing any events.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch view] == mapView_) {
NSLog(#"Touches began");
} else NSLog(#"Touches began");
}
Is there another way to detect user interaction throught touching the screen?
You have to use UITapGestureRecognizer.
Conform your class to UIGestureRecognizerDelegate protocol.
Instantiate the gesture recognizer. For example, to instantiate a UITapGestureRecognizer, we will do:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
Here, action is the selector which will handle the gesture. Here, our selector handleTapFrom will look something like:
- (void) handleTapFrom: (UITapGestureRecognizer *)recognizer
{
//Code to handle the gesture
}
The argument to the selector is the gesture recognizer. We can use this gesture recognizer to access its properties, for example, we can find the state of the gesture recognizer, like, UIGestureRecognizerStateBegan, UIGestureRecognizerStateEnded, etc.
Set the desired properties on the instantiated gesture recognizer. For example, for a UITapGestureRecognizer, we can set the properties numberOfTapsRequired, and numberOfTouchesRequired.
Add the gesture recognizer to the view you want to detect gestures for. In our sample code (I will be sharing that code for your reference), we will add gesture recognizers to an imageView with the following line of code:
[self.imageView addGestureRecognizer:tapGestureRecognizer];
After adding the gesture recognizer to the view, set the delegate for the gesture recognizer, i.e. the class which will handle all the gesture recognizer stuff. In our sample code, it would be like:
tapGestureRecognizer.delegate = self;
Note: Assign the delegate after adding the gesture recognizer to the view. Otherwise, the action method won’t be called.
Reference - Here
The solution was using UIPanGestureRecogniser.
Here's the code that solved the problems and stopped my headache:
UIPanGestureRecognizer *tap = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapFrom:)];
[mapView_ setMultipleTouchEnabled:YES];
[mapView_ setUserInteractionEnabled:YES];
mapView_.gestureRecognizers = #[tap];
And then the selector method:
- (void) handleTapFrom: (UIPanGestureRecognizer*)recogniser {
NSLog(#"Pin");
}
You can subclass UIApplication if you are only interested in whether the user touched the screen or not, and implement this method:
- (void)sendEvent:(UIEvent *)event {
[super sendEvent:event];
if (event.type == UIEventTypeTouches) {
// handling code
}
}
In this case the main.m file would look like this:
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, #"UIApplicationSubclass", #"AppDelegate");
}
}
I am trying to handle tableViewCell's being tapped, but the problem is that this is a "temporary tableView". I have it coded so that it will appear while the user is editing a UITextField, but then I set up a gesture recognizer to set the tableview to hidden as soon as the user clicks somewhere away from the UITextField.
I have the gesture recognizer set up as follows:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(dismissKeyboard)];
[tap setCancelsTouchesInView:NO];
[self.view addGestureRecognizer:tap];
However, dismissKeyboard is called before didSelectRowAtIndexPath is called, and so the TableView that I want to handle the event on becomes hidden and therefore this function is never called.
My question is: Does anybody have ideas of how to get around this, so that didSelectRowAtIndexPath will execute before the tableView hides? I had one idea to somehow see if the tableView is where the tap is coming from, and if so, then don't execute the "hide tableView" line within dismissKeyboard. Is this possible?
Sorry, but I am new to iOS dev, so thank you for any advice!
You should be able to do this by making your view controller the tap gesture's delegate and denying it any touches that are inside the table view. Here is a starting point:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch
{
//Assuming your table view is a direct subview of the gesture recognizer's view
BOOL isInsideTableView = CGRectContainsPoint(tableView.frame, [touch locationInView:gesture.view])
if (isInsideTableView)
return NO;
return YES;
}
Hope this helps!
You could set yourself as a delegate to the UITapGestureRecognizer and cancel the gesture when the user taps within the tableView.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
//You can also (and should) check to make sure the gestureRecognizer is the tapGestureRecognizer
if (touch.view == tableView)
{
return NO;
}
else
{
return YES;
}
}
To better fit what you need, judge if your search bar is first responder.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gesture shouldReceiveTouch:(UITouch *)touch
{
BOOL isInsideTableView = CGRectContainsPoint(yourTabelView.frame, [touch locationInView:gesture.view]);
if (isInsideTableView && ![yourSearchBar isFirstResponder])
return NO;
return YES;
}
In my app I have this code:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[UIScrollView class]]){
return YES;
}
else return NO;
}
In this I control if my touch is inside a scrollView or not but now I want to check if the touch is a simple touch or is a swipe gesture, is there a way to detect it?
thanks
The method you written above is UIGestureRecognizerDelegate. This is a delegate method will get called when particular gesture on which you put an observer, gets detected.
In order to identify swipe gesture, you have to add Gesture recognizer to View on which you want to detect as below:
UISwipeGestureRecognizer *recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[recognizer setDirection:(UISwipeGestureRecognizerDirectionRight)];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];
You can get gesture detection in method handleSwipeForm:
If you want to get the above delegate to get called then also add this line,
recognizer.delegate = self;
Use UISwipeGestureRecognizer to detect swipe gestures (you can set the swipe direction: UISwipeGestureRecognizer.direction)
And a UITapGestureRecognizer to detect taps (UITapGestureRecognizer.numberOfTapsRequired sets the required number of taps to trigger the recognizer (e. g. for double-taps)
You have to use UISwipeGestureRecognizer in order to detect swipe gestures .
UISwipeGestureRecognizer *swipeGest= [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(SwipeRecognizer:)];
[swipeGest setDirection:(UISwipeGestureRecognizerDirectionRight)];
[[self view] addGestureRecognizer:swipeGest];
swipeGest.delegate = self;
setDirection is used to set the swipe detect direction.
- (void)SwipeRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
}
Here we will be writing the function to do after detecting the swipe gesture.