I have tried setting up a simple UITapGestureRecognizer on a UILabel but it is not working. Nothing seems to be recognized and nothing is written to the log.
in a method called from viewDidLoad
UILabel *miTN = [[UILabel alloc] initWithFrame:CGRectMake(300, 100, 150, 15)];
[miTN setUserInteractionEnabled:YES];
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecognized)];
[miTN addGestureRecognizer: tapRecognizer];
[miView addSubview:miTN];
... later
- (void)tapRecognized:(id)sender
{
NSLog(#"that tap was recognized");
}
Also, this is called in response to an async network call. Could that be causing the problem? Is there some other issue that might be causing isssue? I'm not really sure what first step to debug would be - I checked Color Blended Layers to see if they were ovrelapping but don't appear to be.
You should add UIGestureRecognizerDelegate to the protocol list for your viewcontroller class
#interface TSViewController : UIViewController <UIGestureRecognizerDelegate>
and insert string:
tapRecognizer.delegate = self;
and replace
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecognized)];
to
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapRecognized:)];
in Swift, you have to enable by doing this as follows.
yourLabel.isUserInteractionEnabled = true
Related
I have a table where a gesturerecognizer should be added to the table-header-label. This is done through following code:
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTableheaderTap:)];
[headerView addGestureRecognizer:singleFingerTap];
singleFingerTap.delegate = self;
The selector-method looks like following:
- (void)handleTableheaderTap:(UITapGestureRecognizer *)recognizer
Unfortunately, the recognizer is nil, when the method is called. What do I have to change, so the recognizer is in the handletTableheaderTap not nil anymore?
Thank you!
You have to store the instance in a controller attribute.
Declare a private property to store it.
Example :
#interface MyViewController()
#property (nonatomic, strong) UITapGestureRecognizer *singleFingerTap
#end
...
self.singleFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(handleTableheaderTap:)];
[headerView addGestureRecognizer:singleFingerTap];
singleFingerTap.delegate = self;
In a custom class MMTimerButton, I set up the button to respond to a single and a double tap
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setBackgroundColor: [UIColor clearColor]];
UITapGestureRecognizer *singleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
singleTapRecognizer.numberOfTapsRequired=1;
singleTapRecognizer.delaysTouchesEnded=YES;
UITapGestureRecognizer *doubleTapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
doubleTapRecognizer.numberOfTapsRequired=2;
[singleTapRecognizer requireGestureRecognizerToFail: doubleTapRecognizer];
[self addGestureRecognizer:singleTapRecognizer];
[self addGestureRecognizer:doubleTapRecognizer];
}
return self;
}
I implement the two methods like this in the same file
-(void)handleTap:(UITapGestureRecognizer *)sender{
NSLog(#"single tap");
}
-(void)handleDoubleTap:(UITapGestureRecognizer *)sender{
NSLog(#"double tap");
}
In the header, I declare two methods
#import <UIKit/UIKit.h>
#interface MMTimerButton : UIButton
-(void)handleTap:(UITapGestureRecognizer *)sender;
-(void)handleDoubleTap:(UITapGestureRecognizer *)sender;
In the storyboard, I added a button to the interface and set its custom class to be MMTimerButton.
Nothing's happening when I click the button (in the simulator). One click, two click, both nothing.
I also tried doing it without a button, just adding gesture recognizers to the titleView. Nothing happens when I click on the title in the simulator
UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleDoubleTap:)];
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleSingleTap:)];
[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];
[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];
self.navigationItem.title =#"title";
[self.navigationItem.titleView addGestureRecognizer:doubleTap];
[self.navigationItem.titleView addGestureRecognizer:singleTap];
However, when I add this code to header view, it works fine (in the simulator)
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *headerLabel = [[UILabel alloc]init];
headerLabel.tag = section;
headerLabel.userInteractionEnabled = YES;
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.text = [NSString stringWithFormat:#"0:00",section];
headerLabel.textAlignment = UITextAlignmentCenter;
headerLabel.frame=CGRectMake(10,-5,tableView.frame.size.width,41);
UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleDoubleTap:)];
UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget : self action : #selector (handleSingleTap:)];
[singleTap requireGestureRecognizerToFail : doubleTap];
[doubleTap setDelaysTouchesBegan : YES];
[singleTap setDelaysTouchesBegan : YES];
[doubleTap setNumberOfTapsRequired : 2];
[singleTap setNumberOfTapsRequired : 1];
self.navigationItem.title =#"title";
[headerLabel addGestureRecognizer:doubleTap];
[headerLabel addGestureRecognizer:singleTap];
return headerLabel;
//return nil;
}
You are showing a lot of troubled code here, so it's hard to know where to start.
In the case of your initWithFrame:, the problem is that this method is never called for a button. Moreover, you've got a conflict because the button already contains the ability to respond to a tap, internally (it's a button!).
In the second set of code, you never set the titleView to a view, so it is nil, and your code does nothing. Also, you can't set both the title and the titleView (you are setting the title).
The answer to your title question is, of course a titleView can respond to a tap. Lots of apps do this (including mine).
Also, you do not need your requireGestureRecognizerToFail - a single tap gesture recognizer and a double tap gesture recognizer already know how to mediate between themselves.
So basically my advice would be: stop over-complicating everything. Don't make big assumptions and dive in. Start with stuff that you know works and take little steps. Test everything with logging / breakpoints as you go, to see that what's happening is what you imagine.
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.
I know that a "table view header"(the most top-part of a table view) is a View
So I try to add a UITapGestureRecognizer to it ,but it doesn't work...
code is simple :
- (void)tap:(UITapGestureRecognizer *)recognizer
{
// do something
}
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
[self.tableView.tableHeaderView addGestureRecognizer:recognizer];
Any tips here to care ? thanks a lot
Here's the thing that works for me:
Instead adding this:
self.tableView.tableHeaderView
I add gesture recognizer on every UILabel on tableview.
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *headerLabel = [[UILabel alloc]init];
headerLabel.tag = section;
headerLabel.userInteractionEnabled = YES;
headerLabel.backgroundColor = [UIColor greenColor];
headerLabel.text = [NSString stringWithFormat:#"Header No.%d",section];
headerLabel.frame = CGRectMake(0, 0, tableView.tableHeaderView.frame.size.width, tableView.tableHeaderView.frame.size.height);
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(catchHeaderGesture:)];
tapGesture.cancelsTouchesInView = NO;
[headerLabel addGestureRecognizer:tapGesture];
return headerLabel;
//return nil;
}
-(void)catchHeaderGesture:(UIGestureRecognizer*)sender
{
UILabel *caughtLabel = (UILabel*)sender.view;
NSLog(#"header no : %d", caughtLabel.tag);
}
I hope that helps.
First of all
Make sure that you call this code section in viewDidLoad or viewWillAppear
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
[self.tableView.tableHeaderView addGestureRecognizer:recognizer];
Second, please make sure that
self.tableView.tableHeaderView
is not null, add
NSLog([self.tableView.tableHeaderView description]);
And check the console for output
I just tried your code and the tap was recieved correctly
I've two UITapGestureRecognizer: singleTap and doubleTap initialized with two different actions.
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSingleTap:)];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
[singleTap requireGestureRecognizerToFail:doubleTap];
[doubleTap setNumberOfTapsRequired:2];
[imageView addGestureRecognizer:doubleTap];
[imageView addGestureRecognizer:singleTap];
When I run my app in simulator the single tap responds correctly but not the double tap ! When I double clicks nothings happens, I suppose iOS dose recognize the double tap because the action of single tap doesn't being called (due to [singleTap requireGestureRecognizerToFail:doubleTap];), but I can't understand why doesn't it do the action handleDoubleTap.
I think the problem is that UIImageView and UILabel both override the default value of YES for the userInteractionEnabled property, and sets it to NO.
Add imageView.userInteractionEnabled = YES; and try again.
The following code works for me:
- (void)handleTap:(UIGestureRecognizer*)gr {
NSLog(#"----------------- tap ----------------");
}
- (void)handleDoubleTap:(UIGestureRecognizer*)gr {
NSLog(#"================= double tap ============");
}
- (XXXView*)createXXXView {
XXXView *view = [[[XXXView alloc] init] autorelease];
view.xxx=...;//irrelevant
UITapGestureRecognizer *dtr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleDoubleTap:)];
dtr.numberOfTapsRequired = 2;
UIGestureRecognizer *tr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleTap:)];
[tr requireGestureRecognizerToFail:dtr];
[view addGestureRecognizer:tr];
[view addGestureRecognizer:dtr];
return view;
}