rustybeanstalk
rustybeanstalk

Reputation: 2762

Figure out section of a section header when tapped in a UITableView

I have a UITableView with custom views for section headers. I added a UITapGestureRecognizer to the customer sections header views to detect when someone has tapped on a section header.

How do I figure out which section the section headers belong to?

Thanks in advance.

Upvotes: 1

Views: 4254

Answers (5)

Alexandr Kolesnik
Alexandr Kolesnik

Reputation: 2204

You can add button to header and set tag to button something like this:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:
(NSInteger)section {
    UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.height, tableView.frame.size.width)];
    UIButton *button = [[UIButton alloc] initWithFrame:headerView.frame];
    button.tag = section;
    [button addTarget:self action:@selector(detectSection:) forControlEvents:UIControlEventTouchUpInside];
    [headerView addSubView:button];
    return headerView;
}

-(void)detectSection:(UIButton *)sender {
    switch(sender.tag) {
    //your code
    }
}

Upvotes: 0

adamup
adamup

Reputation: 1538

A bit late to the party here, but this can be a difficult problem to solve, especially if (as @klyngbaek mentions in the comments), you are adding/removing sections. Changing a tag or custom index property on the header UIView by reloading entire sections can result in ugly animations.

Try this as a callback method for the gesture recognizer that's attached to each header UIView (admittedly hackey):

- (void)headerTapped:(UITapGestureRecognizer *)sender{

    NSInteger section = 0;
    for(int counter = 0; counter < [self.tableViewOfInterest numberOfSections]; counter++){
        if([[self.tableViewOfInterest headerViewForSection:counter] frame].origin.y == sender.view.frame.origin.y){
            section = counter;
            break;
        }
    }

}

Basically, when asking a UITableView for each section header, it returns an instance of the header with the frame set to the header's position in the table. Comparing this with the frame of the UITapGestureRecognizer's view property will result in a match at some point (no pun intended)!

Upvotes: 0

user1734058
user1734058

Reputation: 51

in the viewDidLoad section insert your gestureRecognizer:

- (void)viewDidLoad
{
    (...)

    UITapGestureRecognizer* doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapTable:)];
    doubleTap.numberOfTapsRequired = 2;
    doubleTap.numberOfTouchesRequired = 1;
    [self.yourTable addGestureRecognizer:doubleTap];

    (...)

}

If you only want to detect single tap change doubleTap.numberOfTapsRequired to 1.

Then add the following method. This will check if the tapped point is inside section header:

-(void)doubleTapTable:(UISwipeGestureRecognizer*)tap
{
    if (UIGestureRecognizerStateEnded == tap.state)
    {
        CGPoint p = [tap locationInView:tap.view];

        NSIndexPath* indexPath = [yourTable indexPathForRowAtPoint:p];

        if(indexPath){  // user taped a cell

            // whatever you want to do if user taped cell

        } else { // otherwise check if section header was clicked 

            NSUInteger i;

            for(i=0;i<[yourTable numberOfSections];i++) {

                CGRect headerViewRect = [yourTable rectForHeaderInSection:i];

                BOOL isInside = CGRectContainsPoint (headerViewRect,
                                                     p);
                if(isInside) {

                    // handle Header View Selection

                    break;
                }

            }
        }

    }
}

Upvotes: 1

Vincent Bernier
Vincent Bernier

Reputation: 8664

The action method that you are providing must have the following signature :

- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer;

And a gestureRecognizer have the following properties :

Getting the Recognizer’s State and View
state property
view property
enabled property

So basically you can ask for the view that it is attached to and interrogate that view.

Upvotes: 1

BoltClock
BoltClock

Reputation: 724502

The easiest way is to designate a property on your section header view class to hold the section index, then assign the index to that property in -tableView:viewForHeaderInSection: like this:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    // CustomHeaderView *headerView = ...

    headerView.section = section;

    // ...
    return headerView;
}

Then have the gesture callback look at that property.

Upvotes: 2

Related Questions