Touch events on UITableView?

57,618

Solution 1

I was facing the problem since a long time and didn't got any working solution. Finally I choose to go with a alternative. I know technically this is not the solution but this may help someone looking for the same for sure.

In my case I want to select a row that will show some option after that I touch anywhere on table or View I want to hide those options or do any task except the row selected previously for that I did following:

  1. Set touch events for the view. This will do the task when you touch anywhere on the view except the table view.

  2. TableView's didSelectRowAtIndexPath do following

     - (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
        if(indexPath.row != previousSelectedRow && previousSelectedRow != -1) {
            // hide options or whatever you want to do
            previousSelectedRow = -1;
        }
        else {
            // show your options or other things
            previousSelectedRow = indexPath.row;
        }
     }
    

I know that this is older post and not a good technical solution but this worked for me. I am posting this answer because this may help someone for sure.

Note: The code written here may have spell mistakes because directly typed here. :)

Solution 2

No need to subclass anything, you can add a UITapGestureRecognizer to the UITableView and absorb the gesture or not depending on your criteria.

In your viewDidLoad:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnTableView:)];
[self.myTableView addGestureRecognizer:tap];

Then, implement your action like this for the criteria:

-(void) didTapOnTableView:(UIGestureRecognizer*) recognizer {
    CGPoint tapLocation = [recognizer locationInView:self.myTableView];
    NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:tapLocation];

    if (indexPath) { //we are in a tableview cell, let the gesture be handled by the view
        recognizer.cancelsTouchesInView = NO;
    } else { // anywhere else, do what is needed for your case
        [self.navigationController popViewControllerAnimated:YES];
    }
}

And note that if you just want to simply pick up clicks anywhere on the table, but not on any buttons in cell rows, you need only use the first code fragment above. A typical example is when you have a UITableView and there is also a UISearchBar. You want to eliminate the search bar when the user clicks, scrolls, etc the table view. Code example...

-(void)viewDidLoad {
    [super viewDidLoad];
    etc ...

    [self _prepareTable];
}
-(void)_prepareTable {
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.allowsSelection = NO;
    etc...

    UITapGestureRecognizer *anyTouch =
        [[UITapGestureRecognizer alloc]
         initWithTarget:self action:@selector(tableTap)];
    [self.tableView addGestureRecognizer:anyTouch];
}
// Always drop the keyboard when the user taps on the table:
// This will correctly NOT affect any buttons in cell rows:
-(void)tableTap {
    [self.searchBar resignFirstResponder];
}
// You probably also want to drop the keyboard when the user is
// scrolling around looking at the table. If so:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
    [self.searchBar resignFirstResponder];
}
// Finally you may or may not want to drop the keyboard when
// a button in one cell row is clicked. If so:
-(void)clickedSomeCellButton... {
    [self.searchBar resignFirstResponder];
    ...
}

Hope it helps someone.

Solution 3

You should forward the touch event to the view's controller. Subclass your tableview control and then override the method:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [super touchesBegan:touches withEvent:event];  //let the tableview handle cell selection 
    [self.nextResponder touchesBegan:touches withEvent:event]; // give the controller a chance for handling touch events 
}

then , you can do what you want in the controller's touch methods.

Solution 4

I just stumbled onto what may be a solution for your problem. Use this code when you create your table view:

tableView.canCancelContentTouches = NO;

Without setting this to NO, the touch events are cancelled as soon as there is even a slight bit of vertical movement in your table view (if you put NSLog statements in your code, you'll see that touchesCancelled is called as soon as the table starts scrolling vertically).

Solution 5

Try this methods:

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{

}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{

}

Use scrollViewDidEndDragging like alternative of touchesEnded. Hope it helps.

Share:
57,618
Kapil Choubisa
Author by

Kapil Choubisa

Love coding :) #SOreadytohelp

Updated on February 21, 2020

Comments

  • Kapil Choubisa
    Kapil Choubisa about 4 years

    I have UIViewControllerand UITableView as child in the view, what I want to do is when I touch any row I am displaying a view at bottom. I want to hide that view if the user touch any where else then rows or the bottomView.

    The problem is when I click on UITableView it doesn't fires touchesEnded event.

    Now how can I detect touch on UITableView and distinguish it with row selection event.

    Thanks.