I've searched through other questions similar to this on SO already, and came up empty with a solution to my problem. For some reason, my UIImageView (which I've added to a UIView in storyboard) just won't recognize a tap gesture I've created. User Interaction is enabled, as is multiple touch. My selector method just never gets called.
self.image is my imageView property that I've added onto a UIView.
- (void)viewDidLoad {
[super viewDidLoad];
self.image.image = [UIImage imageNamed:#"mountainWallpaper.png"];
[self gesture];
}
-(void)gesture {
UITapGestureRecognizer *imageTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(imageTapped:)];
//imageTap.numberOfTapsRequired = 1;
//imageTap.numberOfTouchesRequired = 1;
imageTap.delegate = self;
[self.image addGestureRecognizer:imageTap];
}
-(IBAction3)imageTapped:(UIGestureRecognizer *)tap {
NSLog(#"test");
}
Any suggestions? I've looked through most other questions I found and tried out various solutions with no such luck. Many answers said to verify that user interaction is enabled, to make sure the delegate is set...I've tried much of what has been suggested already.
I've also experimented with first adding the UIView as the tap gesture target, adding the imageView itself as the target, adding the gesture to both the UIView and the imageView...nothing.
In storyboard, I have my UIImageView connected to my viewController as both the view and the image. I generally do things programmatically so I have to get used to connecting objects in IB, I'm pretty bad at it.
Check for following points may be it will helpful for you :
Make sure your UIImageView User interaction is enable .
Image View priority should be on top over super view .
make sure super view of Image view userIntration is also enable .
have you added UI gesture Delegate ?
It looks like you have a spelling mistake. Try changing IBAction3 to IBAction or void:
-(void)imageTapped:(UIGestureRecognizer *)tap {
NSLog(#"test");
}
Related
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.
UITapGestureRecognizer is applied to both UIImageView and its subview (UITextView). However, when I tap on subview, the receiver becomes subview and its parent view (i.e. UIImageView + UITextView). It should however be only subview because that was the one I tapped. I was assuming nested gestures would react first but apparently parent receives the fist tap and then it goes to child.
So, there are different solutions out there for various scenarios (not similar to mine but rather buttons inside scroll view conflict). How can I easily fix my issue without possible subclassing and for iOS 6+ support? I tried delaying touch on start for UIGestureRecognizer on UIImageView and I tried setting cancelsTouchesInView to NO - all with no luck.
Try the following code:
conform the <UIGestureRecognizerDelegate> to your class.
set yourGesture.delegate = self;
then add this delegate Method:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
// return YES (the default) to allow the gesture recognizer to examine the touch object, NO to prevent the gesture recognizer from seeing this touch object.
if([touch.view isKindOfClass: [UITextView class]] == YES)] {
return YES;
}
else {
return NO;
}
}
Hope it will solve your issue. Enjoy Coding..!!!!
That's exactly what is it supposed to do.
View hierarchy is like a tree structure and its traversal during a touch gesture starts from the root node. It is very likely for your parent view to receive gesture first and then its subviews. The traversal skips the nodes for which
userInteractionEnabled = NO.
since, you don't have any code I can't help you to play with this flag. A more general solution is to always set gesture only for your parentView and in the gesture delegates check the coordinates if it belongs to any one of the subview and if yes then call your gesture method for your subview.
Not a clean approach but works. !!
you should implement the UIGestureRecognizer delegate methods and apply the correct policy to the gesture, when multiple gesture are recognized
I have a Button1 outside ScrollView and another Button2 inside scrollview. I am using storyboard. I have used drag drop segue from both buttons to a different view. Button1 works fine, the problem is with Button2, it doesnt work no matter how many times I click, it only works when I click and drag (strange!!). When I troubleshooted I found that whenever I create an outlet of scrollview it behaves this way, if I remove the connection of scrollview to the outlet it works fine, but I need the outlet for the scrollview to work. Any solution on how I can get this done? This is a sample code of my view did load if it helps
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"bg.png"]];
self.scrollView.contentSize =CGSizeMake(320, 500);
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(resignKeyboard)];
[self.scrollView addGestureRecognizer:singleTap];
singleTap.numberOfTapsRequired = 1;
}
-(void) resignKeyboard
{
[self.view endEditing:YES];
}
This is how I defined the outlet
#property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
Note that Button2 Click does work but on click and drag/swipe not on single or multiple clicks.
EDIT:I checked and found that it works fine for simulator 6.1 but not for 5.0
Check out that your button 2 is inside the bounds of scrollview. If button's any part will lie outside the parent container's frame, it will not respond to any events. Test it by changing color of background of the scrollview. Also you can set button2.clipToBounds = YES. If button will be out of bounds, that part will be clipped.
I figured out the problem was because of adding tap gesture, because when your button is inside scrollview the first tap it works for scrollview and not button, so all I had to do is check if touch is for button or not. Here is the code that fixed this issue.
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (self.scrollView.superview != nil) {
if ([touch.view isKindOfClass:[UIButton class]])
{
return NO; // ignore the touch
}
}
return YES; // handle the touch
}
Add delegate UIGestureRecognizerDelegate and in viewdidload add this line in the end
singleTap.delegate = self;
I had similar issue. What I did was remove entire hierarchy involving problematic view (in this case Button 2 and scroll view), then recreate them. Then recreate outlets and IBActions.
This works because storyboard is an xml document and sometimes xcode messes things up in writing it.
My reusable cell contains a view with all its informations (UIImageView, UILabel, etc.) with a frame of 0,0,320,63, named mainView
I also have another subview, added programmatically, with a frame of -160,0,160,63, named leftView, contained in mainView.
I added a UISwipeGestureRecognizer to the cell, so when you swipe, I change the frame of mainView to 160,0,320,63. It works perfectly.
I just have a problem, in leftView, I have some UIImageView with userInteractionEnabled set to YES, with a gesture recognizer on it. But this gesture recognizer is never fired, it still calls the -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method.
I looked at this SO answer, but it does not help me.
Would somebody help me with that ?
Thank you !!
EDIT : Here is my gesture recognizer instantiation
// Selector is valid, I checked it out. _viewController too.
UIImageView * imageView = [[UIImageView alloc] initWithFrame:frame];
[imageView setImage:someImage];
[imageView setUserInteractionEnabled:YES];
[_leftView addSubview:imageView];
UITapGestureRecognizer * gr = [[UITapGestureRecognizer alloc] initWithTarget:_viewController action:selector];
[imageView addGestureRecognizer:gr];
Without seeing the gestureRecognizer's initialization, it could be a number of things that are the problem. Two main things to look into however:
1.) Have you set the cancelsTouchesInView flag? Normally this would be messing with your tableView touches, but you should look into it though.
2.) Have you verified the subview layout inside of storyboard? Is there something blocking part of your imageView?
-Also you've actually allocated the gestureRecognizer correct?
Have you tried to set table cell selectable to No? in this case your swipe gesture should still work, but table deligate method for cell selection shouldn't.
I figured it out myself.
The problem was because the leftView frame was outside of the mainView frame (-160 in x).
To solve my problem, I changed mainView in storyboard, so that it also starts at -160. And instead of adding leftView at -160 in x, I add it at 0.
Thanks anyway !
It may seem like duplicate, but I can't actually find any good answer to my concrete situation.
I have some button with background image (1pt-wide, streched), icon-like image inside along with the text label. It's height is 33pt, I need to make it's hittest area 44pt-high.
I saw two solutions, but neither of them works for me.
First solution is to enlarge frame and adjust image so it would have some padding. But that is not acceptable for me, because I have both background image and image inside the button.
Second solution is to subclass UIButton (which is absolutely acceptable) and override - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event. I did that, when I put some breakpoints in this method and tried to tap in desired area nothing happened (breakpoints worked when tapped inside the button frame).
Are there any other solutions? What could be possibly wrong with the second solution?
If you create the view programmatically, you can instantiate a UIView that is 44px high, add a tap gesture recognizer to it, and add your UIButton as a subview inside this view:
CGRect bigFrame = CGRectMake(0,0,100,44);
UIView *big = [[UIView alloc] initWithFrame:bigFrame];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doPress)];
[big addGestureRecognizer:tapRecognizer];
UIButton *yourButton = ...
[big addSubview:yourButton];
[self.view addSubview:big];
Then implement the selector as:
- (void)doPress {
[yourButton sendActionsForControlEvents:UIControlEventTouchUpInside];
}
In that way, the outer view taps will be interpreted as button presses for your button.