I have a LongPress gesture recognizer initialized in the viewDidLoad method of my viewcontroller as below:
longPressGesture_= [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(displayTimeFlagCallout)];
I have a tableview in my viewcontroller. The tableview has custom cells. Each cell has 2 textfields. I want to bring up a custom popover when a user long presses on the text fields (startTime and endTime). I do not want the magnifying glass and the Copy/Paste popover to show up on long press of textfield as the standard behavior and hence before adding my gesture recognizer, I am disabling the in-built long press gesture recognizer of the text fields. I have added the following code to my cellforRowAtIndexPath method:
MyCustomCell_iPhone *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil)
{
cell = [[MyCustomCell_iPhone alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
for (UIGestureRecognizer *recognizer in cell.startTime.gestureRecognizers) {
if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
recognizer.enabled = NO;
}
}
for (UIGestureRecognizer *recognizer in cell.endTime.gestureRecognizers) {
if ([recognizer isKindOfClass:[UILongPressGestureRecognizer class]]){
recognizer.enabled = NO;
}
}
[cell.startTime addGestureRecognizer:longPressGesture_];
[cell.endTime addGestureRecognizer:longPressGesture_];
}
However, this is not working. Nothing happens on long press now. Any ideas what could be the issue?
Thanks
Hetal
Three thoughts:
You cannot use the same long press gesture recognizers for two controls. You have to create a separate gesture recognizer for each control.
It would appear that the gesture recognizers get reset when you start editing in text field (assuming you allow editing in the text field). I assume you allow editing of the text field, and, if so, I believe that you have to set a delegate that will disable the long gesture recognizer that is not your own. (You can do that, for your long press gesture recognizer, subclass it as, say CustomLongPressGestureRecognizer, use that for your text field's gesture recognizers and then you can disable any UILongPressGestureRecognizer objects that are not your own CustomLongPressGestureRecognizer.)
I infer from your code that you're not using storyboards and prototype cells, because in that scenario, cell is never nil and your if statement would never end up invoking your code. But if you're using NIBs or not using prototype cells, then you should be fine on this point.
Related
I have a UITextView in a UITableViewCell. I have set it to become first responder when the cell is selected as so:
TPNTableViewCell *thisCell = (TPNTableViewCell *)[tblMain cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
thisCell.txtHidden.text=#"";
[thisCell.txtHidden becomeFirstResponder];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(goAwayKeyboard)];
[self.view addGestureRecognizer:tap];
So when the cell is selected txtHidden becomes first responder. And then the selector goAwayKeyboard is triggered when you click out of the keyboard.
-(void)goAwayKeyboard
{
TPNTableViewCell *thisCell = (TPNTableViewCell *)[tblMain cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
[thisCell.txtHidden resignFirstResponder];
}
This works, however after the keyboard is resigned I can no longer select a cell in the table view. I can scroll the table view, but the cells aren't selectable and I can't figure out why.
The tap gesture recognizer is probably swallowing all touch events after it's added to the view. Perhaps removing it in -goAwayKeyboard would restore touch interaction.
You should disable the tap gesture in go away keyboard, You can do this with the help of below code,
tap.enabled = NO;
I have added a UILongPressGestureRecognizer to my UICollectionView that is within a subclass of UIScrollView. (The UIScrollView is paged so there are 3 horizontally stacked UIViewControllers).
My code to add the UILongPressGestureRecognizer:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleLongPress:)];
longPress.delegate = self;
longPress.minimumPressDuration = 0.5;
longPress.delaysTouchesBegan = YES;
[self.collectionView addGestureRecognizer:longPress];
And an NSLog in my handleLongPress: method. Currently I hold down on a UICollectionViewCell, it highlights, but the long press is not activated. I believe my UIScrollView subclass is consuming the long press and not passing along to the UICollectionView. When I lift my finger, the didSelectItemAtIndexPath: method is called.
In my UIScrollView subclass, the only customization I have is the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer {
// This line enables the swipe to delete in the Messaging VC.
return ([otherGestureRecognizer.view.superview isKindOfClass:[UITableView class]]);
}
This was done to enable cell swiping in my UITableView, which is one of the pages of my UIScrollView. The swiping works no problem, and I have tried a number of similar checks for UICollectionView and UICollectionViewCell here but have not gotten the long press to register yet. Any advice appreciated.
Edit: I have added the long press on another UICollectionView and it is functional, but the cell never shows highlighted/selected status. I guess that is a clue as to why I can't get this long press gesture to fire.
My issue was that I was adding the gesture recognizer in the -init method. That did not work. Simply moving the code to -viewDidLoad fixed the problem.
I have a UITableView with a couple of UITableViewCells in it. Because I only have a couple of cells, there is an area of the table view that's not covered by the cells. And I want to do something when the empty area is tapped.
I tried adding a UITapGestureRecognizer on the table view. It detects the tapping on the empty area, but then the cells fail to respond to tapping. I tried adding the tap gesture recognizer on the super view of the table view, but the result is the same.
There must be a way to do this, but I can't quite figure it out yet. Is there any way to achieve what I want to do?
Try this:
initialize and add the UITapGestureRecognizer to your tableView:
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
gr.delaysTouchesBegan = YES;
gr.delegate = self;
[_tableView addGestureRecognizer:gr];
implement the gesture recognizer delegate method:
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
CGPoint tapPoint = [gestureRecognizer locationInView:_tableView];
UIView * clickedView = [_tableView hitTest:tapPoint withEvent:nil];
NSString *viewClassName = NSStringFromClass(clickedView.class);
return ![viewClassName hasPrefix:#"UITableViewCell"];
}
this way every tap you do outsude cells (but inside the tableview) will be recognized with your UITapGestureRecognizer
The last line: return ![viewClassName hasPrefix:#"UITableViewCell"];
should be changed to return [viewClassName hasPrefix:#"UITableView"]; since the cell you are clicking doesn't have to be a UITableViewCell, but a UIView or some other custom view
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
I have 3 UILabels in each cell of a table. I have added tap gesture recognisers to each one, but when it is tapped, how can I get the index path of the row that was tapped?
Here is my code
UILabel *tit_lbl=[[UILabel alloc]initWithFrame:CGRectMake(10,10,280,45)];
[tit_lbl setText:[[final_dictionaires_array objectAtIndex:indexPath.row] objectForKey:title]];
[tit_lbl setUserInteractionEnabled:YES];
[tit_lbl setTag:indexPath.row];
[btn addSubview:tit_lbl];
[tit_lbl release];
UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(goToArticleDetailsView:)];
[tit_lbl addGestureRecognizer:tapRecognizer];
[tapRecognizer release];
With this, I can get the label action but I want to get which label is clicked in which Row ?? (I have 3 labels in each row).
I agree with the suggestions for using a button with a custom style instead of basically recreating buttons using labels and gesture recognisers. However, you'd still have the same problem. Which label was tapped? And which row of the table was it in?
You can find out which label was tapped by assigning tags to each one and then querying the view property of the gesture recogniser. The gesture recogniser will be the argument in your goToArticleDetailsView method:
-(void)goToArticleDetailsView:(id)sender
{
UITapGestureRecognizer *tapGR = (UITapGestureRecognizer*)sender;
if (tapGR.view.tag == 1)
// tapGR.view is the label that the gesture recognize was attached to
You can find out which row of the table was tapped using the gesture recogniser's locationOfTouch method, together with UITableView's indexPathForRowAtPoint: method:
CGPoint touchLocation = [tapGR locationOfTouch:0 inView:self.tableView];
NSIndexPath *tappedRow = [self.tableView indexPathForRowAtPoint:touchLocation];
A UILabel can not be clicked. You should use the UITextfield if you want to let the user to interact with the values.
To get the action you should sent a message to the instance of UITextField.
To get the right cell you can use the "indexPath"
good luck