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,
- First, Define the
UITapGestureRecognizer
and the action within theUITableViewCell
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
}
}
- 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
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
Property 'Self.*' Not Initialized at Super.Init Call
Makekeywindow VS Makekeyandvisible
A Lighter Way of Discovering Text Writing Direction
What Does $0 Represent in Closures in Swift
Initializing Swift Properties That Require "Self" as an Argument
Bounce Animation on Google Map Marker in iOS? [Objective-C]
The Proper Way of Doing Chain Animations
Getting Location for an iOS App When It Is in the Background and Even Killed
iOS Notification Trigger: Fortnightly And/Or Quarterly
How to Code the Launchscreen Programmatically
Uiwebview Not Go to Didfailloadwitherror When Weblink Not Found
Uisegmentedcontrol iOS 13 Clear Color
Undefined Symbols for Architecture Armv7 for Cocoapods Libraries
How to Create Multi Line Uisegmentedcontrol
Autolayout: Uiview Within Uiview Has Incorrect Frame
How to Switch to Speaker Output When Bluetooth Headsets Are Connected