How to identify touch on UIView subview - ios

I have a scrollview. Inside the scrollview, I have three subviews, A, B, C. When I click on subview A, I want to get either its tag value or know which view I've clicked. I've gone through many codes and blogs, but couldn't find a solution for it.
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {}
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{} //This function is not working with sub view.
Tried these methods but didn't solve my problem.

Use UITapGestureRecognizer. Add a tap gesture recognizer to each of A, B, C views, set the delegate to the view controller and you will be notified on each tap.
UITapGestureRecognizer* tgrA = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[viewA addGestureRecognizer:tgrA];
...
-(void) handleTapGesture:(UIGestureRecognizer *)sender
{
//sender.view.tag will give you what you need.
}
More information on tap gesture recognizer here:
https://developer.apple.com/library/ios/documentation/uikit/reference/UITapGestureRecognizer_Class/Reference/Reference.html

Related

How to receive touch event behind another view?

I have two subviews inside the view. The frame is equal. A view has a swipe left gesture recognizer and B view has a swipe right gesture recognizer. B is behind A so I can only trigger swipe left gesture. How can I receive both?
The view in the back will not respond because, well, it's in the back.
For both gestures to respond simultaneously (left+right at the same time), add a UIGestureRecognizerDelegate to either and handle shouldRecognizeSimultaneouslyWithGestureRecognizer as suggested below.
If you want B to respond to a gesture, even though it is partially hidden by A, rethink your hierarchy: add a 3rd view above A & B (call it C), same size as B, as a placeholder to your gesture recognizer.
Your delegate:
// leftGesture
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer
*)otherGestureRecognizer
{
return otherGestureRecognizer == rightGesture;
}
How can I receive both?
Add both gesture recognizers to view A, since that's the view in front. Since you need the right swipe gesture to be handled by view B, make view B the target for the right swipe gesture recognizer.
A better option might be to make your view controller the target of both gesture recognizers and let it sort out what to do with the user's gestures. That helps to get the views out of the business of knowing how the user interface is set up -- they just have to follow instructions from the view controller. If you adopt that plan, your view controller might look like this in part:
- (void)viewDidLoad
{
UISwipeGestureController *leftSwipe = [[UISwipeGestureController alloc] initWithTarget:self action:#selector(leftSwipe:)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
UISwipeGestureController *rightSwipe = [[UISwipeGestureController alloc] initWithTarget:self action:#selector(rightSwipe:)];
rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
[self.viewA addGestureRecognizer:leftSwipe];
[self.viewA addGestureRecognizer:rightSwipe];
}
- (IBAction)leftSwipe:(id)sender
{
[self.viewA doSomething];
}
- (IBAction)rightSwipe:(id)sender
{
[self.viewB doSomethingElse];
}

Hide UITableView on touches outside the tableview

I have a small UITableView that is hidden when the view is loaded. When i click on "SHOW" UIButton, the UITableView is made visible by myTableView.hidden=NO;
I want to hide UITableView when a user touches outside its frame. Thanks for any help!
Best Approach
Simple.Before show up the UITable View add one more grayed out/Transparent view then add tap gesture recogniser on it to hide it . That's it.
Show Overlay View first - alpha will be 0.5f and background color should be clear color.
show the table view.
NOTE: over lay view should have tap recogniser which will hide the overlay and table view
in View did load
UITapGestureRecognizer *tapRecog = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(overlayDidTap:)];
[myOverLayView addGestureRecognizer:tapRecog];
- (void)overlayDidTap:(UITapGestureRecognizer *)gesture
{
//hide both overlay and table view here
}
Bad Approach
We should not add tap recogniser on main view itself. Because it may have lots of
controls inside of it. so when user tap on it. it will perform its operation. So to avoid
it we can simulate the same behaviour by above approach
You can get touch position by this:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTapGestureCaptured:)];
[self.view addGestureRecognizer:singleTap];
- (void)singleTapGestureCaptured:(UITapGestureRecognizer *)gesture
{
CGPoint touchPoint=[gesture locationInView:self.View];
}
Then just check if the point is in tableview frame. If not then hide the tableview. Hope this help. :)
Subclass UITableView, override pointInside:withEvent:. It is templated for this reason.
Something like:
-(BOOL)pointInside:(CGPoint) point withEvent:(UIEvent*) event
{
BOOL pointIsInsideTableView = [super pointInside:point withEvent:event];
BOOL pointIsOutsideTableView = // Some test
return pointIsInsideTableView || pointIsOutsideTableView;
}
So you can catch the touch in table view implementation, where it belongs logically in this case.

Why does this UITapGestureRecognizer not recognize taps?

I'm having a bit of a problem with a UITapGestureRecognizer. I create it this way:
self.userInteractionEnabled = YES;
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
tapRecognizer.cancelsTouchesInView = NO;
tapRecognizer.delaysTouchesBegan = YES;
tapRecognizer.delegate = self;
tapRecognizer.numberOfTapsRequired = 1;
tapRecognizer.numberOfTouchesRequired = 1;
[self addGestureRecognizer:tapRecognizer];
In the header file I also include and implement the shouldReceiveTouch: method like so:
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
I've looked through countless threads of people with similar problems and can't seem to find a solution. I've heard that if the view you're adding the gesture recognizer has subviews with userInteractionEnabled set to YES, that could possibly interfere with the tap recognition, so I also include this:
for(UIView *subview in self.subviews) {
subview.userInteractionEnabled = NO;
}
Anyone know why the gesture recognizer doesn't work?
Edit:
Here are some details:
I'm adding the UITapGestureRecognizer to a UIView subclass.
I add the gesture recognizer in the subclass' initWithFrame: method.
I've verified that the gesture recognizer is being added by stepping through the portion of the code where it's actually added.
The view controller that contains this view does not have any gesture recognizers attached to it, but does implement touchesBegan, touchesMoved, and touchesEnded. However, according to this question, that the view controller implements those shouldn't affect the gesture recognition of the view.
Edit 2:
I've verified that there are no other views blocking the view with the gesture recognizer from receiving touches. I've also verified that the view is actually being added to the containing view controller's view. It seems like the problem's elsewhere.
Your set up should work, so I would guess that one of two things is happening. You may have forgotten to actually add this view to the ViewController's view, or there maybe another view placed on top of this view which is stealing the touches?
Another possibility causing the problem is that the view on which the UITapGestureRecognizer is added is not big enough, so when you tap on the screen, the touch point is not located in the view's bounds.
Also make sure the UIView is not transparent. Set the background color to e.g. black. This solved the problem for me.

Get UITapGestureRecognizer to recognize touches when they begin?

Is there any way to get UITapGestureRecognizer to run on touch began?
I can't use touchesBegan because I am using a UITableView and the super view steals the event essentially.
I just want to detect when the screen is first touched. Why is this so difficult? Maybe I need a different solution than using tapgesturerecognizer?
You can use state property of UIGestureRecognizer to identify various states of any gesture -
#property(nonatomic,readonly) UIGestureRecognizerState state; // the current state of the gesture recognizer
So when the gesture begin, use something like this in your registered handler method -
if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
// Do your stuff
}
You can add a tap gesture recognizer to the tableView in viewDidLoad like this:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapGestureRecognized:)];
[self.tableView addGestureRecognizer:tapGestureRecognizer];
Then implement this method:
- (void)tapGestureRecognized:(UITapGestureRecognizer *)tapGestureRecognizer {
NSLog(#"tap gesture recognized");
}
Just tested this out, and works fine. For every tap i get the log message on my console. Note that this prevents the tableview from receiving the taps, other gestures will just be handled by the table view as usual.
You need to set delaysContentTouches = NO

Homemade tap gesture recognizer for iOS

I'd like to code my own tap gesture recognizer, to detect the number of taps and number of touches (I don't want to use the iOS tap gesture recognizer because I want to extend it later in various other manners) ;
I tried the following : use the first motionBegin number of touches as the numberOfTouches of the tap, increment the numberOfTaps, and start the tap detection timer to detect the tap gesture if no new taps has been seen in a while
The problem is that one quickly realises that when doing a double-touch tap gesture, iOS either correctly detects one motionBegin with a double touch, or two quick one touch events. I guess a correct implementation should try to detect those quick one touch events that happen closely, but I'm wondering if there is a better way to implement the gesture recognizer.
Someone knows how the iOS tap gesture is implemented?
1. Add UIGestureRecognizerDelegate in your .h file. like
#interface finalScreenViewController : UIViewController <UIGestureRecognizerDelegate>
{
// do your stuff
}
2. Create a view in your viewDidLoad method (or any other method) you wanna to add the gesture in your .m file
ex
UIView * myView=[[UIView alloc]init];
myView.frame=CGRectMake(0,0.self.view.frame.size.width,self.view.frame.size.height);
[self.view addSubView: myView];
UITapGestureRecognizer *letterTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapMethod:)];
letterTapRecognizer.numberOfTapsRequired = 1;
[myView addGestureRecognizer:letterTapRecognizer];
3. you can get view by
- (void) tapMethod:(UITapGestureRecognizer*)sender {
UIView *view = sender.view;
NSLog(#"%d", view.tag);//By tag, you can find out where you had tapped.
}

Resources