How to Detect Tap on Clear Part of Uitableview

How to detect tap on clear part of UITableView?

Yes, there are delegate methods, such as:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

However, this will only tell you if a tap occurs on an existing row. If you want to capture taps on the empty space below the rows (or on a section header) you will need to use a gesture recognizer. You can do something like this:

// in viewDidLoad or somewhere similar
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tableTapped:)];
[self.tableView addGestureRecognizer:tap];
//.........

- (void)tableTapped:(UITapGestureRecognizer *)tap
{
CGPoint location = [tap locationInView:self.tableView];
NSIndexPath *path = [self.tableView indexPathForRowAtPoint:location];

if(path)
{
// tap was on existing row, so pass it to the delegate method
[self tableView:self.tableView didSelectRowAtIndexPath:path];
}
else
{
// handle tap on empty space below existing rows however you want
}
}

EDIT: for an alternative approach, consider Connor Neville's approach from his answer on this post and add the gesture recognizer to the table's background.

How do I detect taps on a UITableView outside of UITableViewCells - i.e. in the section heading?

Here is the code that I went with.

1 Add a tap gesture recognizer to the table. Set Cancels touches in view unchecked.

2 Allow the gestures through the table.

#pragma mark - UIGestureRecognizerDelegate

/**
* Prevents the tap gesture recognizer in the table from gobbling taps
* and allows the table to perform tableView:didSelectRowAtIndexPath:
* <p>
* The gesture recognizer must have cancelsTouchesInView == NO to allow
* the touches through to the table.
* <p>
* The action must check that the tap occurred outside of cells.
*
* @see handleTap:
*/
- (BOOL) gestureRecognizer:(UIGestureRecognizer*)recognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)o {
return recognizer.view == self.table;
}

3 Check the tap is not in a cell.

/**
* Filters a tap on the table to those on the headers/footer.
* <p>
* Note, indexPathForRowAtPoint: has a bug and returns valid indexPaths
* for taps in the last section header and table footer. So an extra
* check is made to ensure that the tap was, in fact, in the cell.
*/
- (IBAction) handleTap:(UITapGestureRecognizer*)tap {
if (UIGestureRecognizerStateEnded == tap.state) {
CGPoint point = [tap locationInView:tap.view];
NSIndexPath* index = [self.table indexPathForRowAtPoint:point];
UITableViewCell* cell;

if (index) {
cell = [self.table cellForRowAtIndexPath:index];
point = [tap locationInView:cell];

if (point.y < 0 || point.y >= cell.frame.size.height) {
index = nil;
}
}

if (!index) {
[self.view performSelector:@selector(endEditing:)
withObject:@(YES) afterDelay:0];
}
}
}

How to handle a tapping on non-cell area of UITableView

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

How to detect a tap/touch in a table view below the cells?

In addition to adding the UITapGestureRecognizer, you need to implement a delegate method and and assign the delegate to the gesture recognizer. First somewhere in your view controller:

UITapGestrueRecognizer *tapRecognizer = ...;
tapRecognizer.delegate = self;

And here is the delegate method to implement:

-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
CGPoint location = [gestureRecognizer locationInView:self.tableView];
NSIndexPath *indexPath = self.tableView indexPathForRowAtPoint:location];
return (indexPath == nil);
}

The delegate method checks if the tap occurred in the cells or not, and if not, it doesn't start recognizing the tap in order to give the table view the chance to interpret the gesture.

Swift recognize tableView cell tap area

According to this thread, adding a Gesture recognizer can conflict with the TableView interactions.

Hence, To achieve what you require, you will have to add a gesture recognizer to the contentView of the UITableViewCell and get the tapped location of the gesture. For this,

  1. First, Define the UITapGestureRecognizer and the action within the UITableViewCell class. Refer the following code
    lazy var tap = UITapGestureRecognizer(target: self, action: #selector(didTapScreen))
.
.
.
// Gesture action
@objc func didTapScreen(touch: UITapGestureRecognizer) {
let xLoc = touch.location(in: self.contentView).x // Getting the location of tap
if xLoc > contentView.bounds.width/2 {
// RIGHT
} else {
// LEFT
}
}

  1. Add the following to the init() method of the custom cell as follows
    override init(frame: CGRect) {
super.init(frame: frame)
tap.numberOfTapsRequired = 1
contentView.addGestureRecognizer(tap)
// Other setups
}

I tried the code in a UICollectionViewCell and got the following output

Sample Image

Detect Tap on UIImageView within UITableViewCell

Maybe not the ideal solution, but add tags to each of the UIImageViews. Then have an NSArray with the uid's corresponding to the tag values

So somewhere in your code make the array

NSArray *testArray = [NSArray arrayWithObjects:@"uid1", @"uid2", @"uid3", @"uid4", @"uid5", @"uid6", nil];

Then when you're setting up the tableview cells set the tag to the row #

//Set the tag of the imageview to be equal to the row number 
cell.imageView.tag = indexPath.row;

//Sets up taprecognizer for each imageview
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:@selector(handleTap:)];
[cell.imageView addGestureRecognizer:tap];

//Enable the image to be clicked
cell.imageView.userInteractionEnabled = YES;

Then in the method that gets called you can get the tag like this

- (void)handleTap:(UITapGestureRecognizer *)recognizer  
{
NSString *uid = testArray[recognizer.view.tag];
}

Detect Taps in Different areas of a tableViewCell

To get the UITableViewCell that was tapped (as an Action of the Button), you have different options:

1) Use Target-Action method, something like:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! cell
//...More Code

myCell.myBtn.addTarget(self, action: "myActionMethod:", forControlEvents: .TouchUpInside)

//... More Code

return myCell
}

And then define your action method (note, yourTbl is an instance of UITableView):

func myActionMethod(sender:UIButton){
//base on the hierarchy of the UI
//Suppose in this case:
//(UITableView)->(UITableViewCell)->(ContentView)->UIButton then:
if let tableViewCell = sender.superview?.superview as? UITableViewCell, indexPath = yourTbl.indexPathForCell(tableViewCell){
//Here you have the IndexPath
}
}

2) The same Idea, but basically your going to set the Tag property of the UIButton (to your row cell), and using Target-Action on the sender (parameter) you get the tag of the button.

Update Sample:
https://github.com/Abreu0101/SampleTargetActionMethod



Related Topics



Leave a reply



Submit