Adding Tap GestureRecognizer to MKOverlay - ios

I am trying to get overlays on my map to responds to touches. Hence, I wanted to add a UIGestureRecognizer for taps to the MKOverlayView that is created in the method mapView:viewForOverlay.
I added the following code in this method:
if ([overlay isKindOfClass:[MKPolygon class]])
{
MKPolygonView* aView = [[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
tap.delegate = self;
aView.fillColor = color;
aView.strokeColor = color;
aView.lineWidth = 2;
[aView addGestureRecognizer:tap];
return aView;
}
In addition, I conform to the UIGestureRecognizerDelegate - Protocol and I implemented the method handleGesture:. So far this method is never called.
Any ideas what I am doing wrong?
Thanks!

Related

UITableView and UIView gesture conflict

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
}

Onclick Event UIView, while using multiple UIViews

I am new in IOS Dev, was searching onclick event for UIView and i found this code that worked perfectly. But it doesnt call specific UIView as i am using multiple UIViews and want to add event on all of them separately while this code calls handleSingleTap onclick of either UIView. plz help..
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleFingerTap];
}
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
CGPoint location = [recognizer locationInView:[recognizer.view superview]];
NSLog(#"Clicked");
}
You can create UITapGestureRecognizer and add it to the views you want it to be clicked.
You can also set up tag property on each view to find out which view was clicked.
For example:
UITapGestureRecognizer *singleFingerTap1 =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
view1.tag = 1;
[view1 addGestureRecognizer:singleFingerTap1];
UITapGestureRecognizer *singleFingerTap2 =
[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
view2.tag = 2;
[view2 addGestureRecognizer:singleFingerTap2];
//..and so on
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer {
UIView *viewClicked = recognizer.view;
NSLog(#"Clicked: %d", viewClicked.tag);
}
The other solution is add one gesture recogniser to the main view (the view which hold the others view, something as you posted) and in handleSingleTap: method check if the point is inside the view:
BOOL isPointInsideView1 = [view1 pointInside:location withEvent:nil];
BOOL isPointInsideView2 = [view1 pointInside:location withEvent:nil];
But ic can failed when one view override another.

selector function not called when adding list of image views with tap gesture recognizer

I have trouble with creating list of ImageViews with tap gesture. When I create gesture, selector function is not called. When I create only one imageView function is called. Any idea why? It is all subview of a large scroll view.
This is my code:
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTaped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
for(int k=0;k<MyList.count;k++){
for(int i=0;i<listSize;i++){
UIImageView *clickForDetail =[[UIImageView alloc]initWithFrame:CGRectMake(i*HELLO_WIDTH,k*LIST_ROW_HEIGH ,HELLO_WIDTH, LIST_ROW_HEIGH)];
clickForDetail.backgroundColor = [UIColor clearColor];
clickForDetail.tag = tag;
clickForDetail.userInteractionEnabled = YES;
[clickForDetail addGestureRecognizer:singleTap];
[myScroll addSubview:clickForDetail];
tag++;
}
}
and selector function:
-(void)imageTaped: (UITapGestureRecognizer *)recognizer
{
NSLog(#"single Tap on imageview");
}
Is it possible somehow to get tag of a ImageView that is clicked?
You need to put different tap gesture for each view object
for(int k=0;k<MyList.count;k++){
for(int i=0;i<listSize;i++){
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTaped:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
UIImageView *clickForDetail =[[UIImageView alloc]initWithFrame:CGRectMake(i*HELLO_WIDTH,k*LIST_ROW_HEIGH ,HELLO_WIDTH, LIST_ROW_HEIGH)];
clickForDetail.backgroundColor = [UIColor clearColor];
clickForDetail.tag = tag;
clickForDetail.userInteractionEnabled = YES;
[clickForDetail addGestureRecognizer:singleTap];
[epgScroll addSubview:clickForDetail];
tag++;
}
}
-(void)imageTaped: (UITapGestureRecognizer *)recognizer
{
NSLog(#"single Tap on imageview");
UIImageView *selectedTextView = (UIImageView *)recognizer.view;
}

How do I get UIGestureRecognizers to work?

I'm having trouble just turning on gesture recognizers in my code. I added a handleTap callback to to the tap gesture recognizer but the print statement never happens. I'm just not having any luck. Does anyone see what I'm doing wrong here?
In my ViewController.h
#interface ViewController : UIViewController<UITextFieldDelegate, UIGestureRecognizerDelegate> {
}
#end
This is what I have in my ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
View *myview = [[View alloc] initWithFrame:applicationFrame];
myview.userInteractionEnabled = YES;
myview.multipleTouchEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTap)];
tap.numberOfTapsRequired = 1;
tap.delegate = self;
[myview addGestureRecognizer:tap];
self.view = myview;
}
-(void)handleTap:(UITapGestureRecognizer*)recognizer {
NSLog(#"dismiss keyboard");
//[usernameTextField resignFirstResponder];
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return YES;
}
Edit: I added a text field and when I click on the text field I see the tap selector print statement. But if I tap off the text field I don't get the selector print statement.
I think the problem is with your selector. Try changing
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTap)];
And replace it with
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTap:)];
To make the selector match the signature for handleTap.
You are passing the wrong selector when initialising.
The line should read like this:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleTap:)];
Notice the colon after handleTap to match the method you want to use.
Apparently subclassing the UIView and overriding drawrect with an empty function caused the selector to be called.

UIGestureRecognizer in UIView Object

I have created a UIViewController, which contains a UIView object.
I want the UIView object response to a single tap by 1 finger, and also pinch by 2 fingers.
I have clicked the "User Interaction Enabled" and the "Multiple touch" options in the xib.
I create both UITapGestureRecognizer, and UIPinchGestureRecognizer inside the UIView function initWithFrame:, as it is the only entry point for the UIView object. But the object doesn't response to the UIGestureRecognizer objects. Why? Or, where is the best place to put the UIGestureRecognizer objects?
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// single tap
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer: singleTap];
// 2 fingers pinch
UIPinchGestureRecognizer* doubleMove = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleMove:)];
[self addGestureRecognizer: doubleMove];
}
return self;
}
Your problem is that when you instantiate your custom view subclass in IB, initWithCoder: is called. If you had done it programmatically using initWithFrame: it would have worked properly.
Two ways you can fix this,
Move the gestures setup to a different method and call them in both initWithFrame: and initWithCoder:. I would recommend doing this if you intend to reuse this component and expose some kind of callbacks on gestures.
If you want to implement this once and have a lot of interacting with the controller element, add them in viewDidLoad.
I tried your code and it works for me.
Where are you setting the view? Maybe it has any other view in front, or its superview has userInteractionEnabled disabled.
I created a UIView subclass and added this code:
-(void) handleSingleTap:(UITapGestureRecognizer *)gr {
NSLog(#"handleSingleTap");
}
-(void) handleDoubleMove:(UIPinchGestureRecognizer *)gr {
NSLog(#"handleDoubleMove");
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
// single tap
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
singleTap.numberOfTapsRequired = 1;
singleTap.numberOfTouchesRequired = 1;
[self addGestureRecognizer: singleTap];
// 2 fingers pinch
UIPinchGestureRecognizer* doubleMove = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleMove:)];
[self addGestureRecognizer: doubleMove];
}
return self;
}
Then, in my controller:
-(void) viewDidLoad {
[super viewDidLoad];
MyView * myView = [[MyView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
myView.backgroundColor = [UIColor greenColor];
[self.view addSubview:myView];
[myView release];
}
And it works.
i think if you are working with .xib, initialization can also be done in
-(void)awakeFormNib;
Adding the GestureRecognizers is typically done in the viewDidLoad method of the UIViewController.

Resources