Reputation: 6359
I have sometimes a header section (just one as I have only one section). I added a gesture (single tap) like the following:
let singleTap = UIShortTapGestureRecognizer(target: self, action: "singleTap:")
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
tableView.headerViewForSection(0)?.addGestureRecognizer(singleTap)
It works. The problem is that when my tableView has just a few rows, if I tap below the last row (on a blank space), it triggers the gesture as well.
How to avoid it? I was thinking a way might be to check if the location of the tap is within the bounds of the header but I don't know how to do it.
For a normal row it's easy, I just use tableView.indexPathForRowAtPoint(point: CGPoint)
but what about for a header?
EDIT:
It seems I need to register my header to get something when I call tableView.headerViewForSection(0)
but the problem is that my header is an UIView
, not a UITableViewHeaderFooterView
or UITableViewCell
so I cannot register it (I think...).
It was working so far because I added the gesture on the table view as well.
So as the gesture is added on the whole tableView, when I get the view from the gesture, I get the tableView and not the header.
So what I've done is get the header from the tableView using its tag:
let header = tableView.viewWithTag(Tag.Header.rawValue)
and then check the location of the tap if it is inside the header view:
let location = sender.locationInView(sender.view)
if header!.pointInside(location, withEvent: nil) { ... }
Upvotes: 3
Views: 10867
Reputation: 2279
I had the same problem and the solution I came up with was to create different targets on a button inside the viewForHeaderInSection
method based on the section. I am using a button but this should work just as well with UITapGestureRecognizer
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// ...
if section == 0 {
cell.button.addTarget(self, action: #selector(firstSectionTapped(_:)), for: .touchUpInside)
} else if section == 1 {
cell.button.addTarget(self, action: #selector(secondSectionTapped(_:)), for: .touchUpInside)
}
// ...
}
Then in the ViewController:
@objc func goalCategoryTapped(_ sender: UITapGestureRecognizer?) {
print("Section One Tapped")
}
@objc func ideaCategoryTapped(_ sender: UITapGestureRecognizer?) {
print("Section Two Tapped")
}
Upvotes: 0
Reputation: 15566
An easy way to do this is to just attach the listener when the table notifies you (via UITableViewDelegate
) it is about to display a header:
override func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let singleTap = // setup gesture
// Add gesture to already created header
view.addGestureRecognizer(singleTap)
}
Then you can just setup the selector function:
func singleTap(gesture: UITapGestureRecognizer) {
let headerView = gesture.view
// Do something with header view
}
Upvotes: 5
Reputation: 23078
A possible better approach is to set the gestureRecognizer on the mainView of the viewController (the tableView) and to detect the tapped view in the gestureRecognizer's gesture action:
{
let singleTap = UIShortTapGestureRecognizer(target: self, action: "singleTap:")
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
tableView.addGestureRecognizer(singleTap) // <--
}
...
@IBAction func singleTap(tapGestureRecognizer: UIShortTapGestureRecognizer) {
// detect the tapped view
var loc = tapGestureRecognizer.locationInView(self.tableView)
if (CGRectContainsPoint(tableView.headerViewForSection(0)?.frame, loc)) {
// header was tapped
...
}
}
Upvotes: 8
Reputation: 273
Try to add Tag for your HeaderView.
-(void) selectheader:(UITapGestureRecognizer *)gestureRecognizer{
UIView *headerView = gestureRecognizer.view;
if (headerView.tag) {
}
}
And
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 18)];
view.tag = section;
// add your gesture
return view;
}
Upvotes: 3