how can I distinguish which part of UITableViewCell has been clicked
Asked Answered
B

5

16

I have created a UITableView with a custom UITableViewCell. My cell includes one UIImageView on the left and UITextView on the right.

Inside UITableViewController, I set both image and text in tableview cellForRowAtIndexPath.

Everything shows fine but now I need to implement didSelectRowAtIndex and I need to distinguish if UIImageView or UITextView of the cell has been clicked.

Let's say, image clicking is representing delete action and the rest of the cell editing action.

Billiot answered 17/6, 2012 at 11:13 Comment(0)
G
50

Rather than adding the gesture recognisers to each individual cell, you can add one to the table view and determine which cell was selected from the point of the users touch, and then determine if the user touched the image or the cell.

First make sure your controller adopts the UIGestureRecognizerDelegate protocol.

@interface MyTableViewController() <UIGestureRecognizerDelegate>
@end

Then add the UIGestureRecognizer to the UITableView when the view loads.

    - (void)viewDidLoad
{
    [super viewDidLoad];
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    singleTap.delegate = self;
    singleTap.numberOfTapsRequired = 1;
    singleTap.numberOfTouchesRequired = 1;
    [self.tableView addGestureRecognizer:singleTap];
}

This delegate method determines if the handleTap: method should be executed. If it can find an indexPath from the users touch, then it returns YES otherwise it returns NO.

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    UITableView *tableView = (UITableView *)gestureRecognizer.view;
    CGPoint p = [gestureRecognizer locationInView:gestureRecognizer.view];
    if ([tableView indexPathForRowAtPoint:p]) {
        return YES;
    }
    return NO;
}

Once we have determined if the user has clicked in a cell, the handleTap: method is called, which then decides if the user touched the image, or any other part of the cell.

- (void)handleTap:(UITapGestureRecognizer *)tap
{
    if (UIGestureRecognizerStateEnded == tap.state) {
        UITableView *tableView = (UITableView *)tap.view;
        CGPoint p = [tap locationInView:tap.view];
        NSIndexPath* indexPath = [tableView indexPathForRowAtPoint:p];
        [tableView deselectRowAtIndexPath:indexPath animated:NO];
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
        CGPoint pointInCell = [tap locationInView:cell];
        if (CGRectContainsPoint(cell.imageView.frame, pointInCell)) {
            // user tapped image
        } else {
            // user tapped cell
        }
    }
}
Guildhall answered 17/6, 2012 at 12:16 Comment(1)
For those that don't know. All the UITapGestureRecognizer setup in viewDidLoad can also be done in Xcode UI layout (aka IB). You'll want to change the return type of handleTap: to IBAction.Jericajericho
I
5

You could subclass UITableViewCell and override touchesEnded.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

    [super touchesEnded:touches withEvent:event];

    UITouch *touch = [touches  anyObject];
    CGPoint location = [touch locationInView:self];

    UIView *hitView = [self hitTest:location withEvent:event];

    if (hitView == myImageView) ...;
    if (hitView == myTextView) ...;
}

You need to keep some reference to your UIImageView and UITextView (they should probably be properties of your cell).

You can of course override touchesBegan instead of touchesEnded, depends on what functionality you want to achieve.

Irradiance answered 17/6, 2012 at 11:31 Comment(0)
T
1

a very abstract and general answer is to do the following For each UIImage and UILabel you add set their tag to be the indexPath.row

//When creating the label and image add a recognizer to them
label.tag = indexPath.row;
imageView.tag = indexPath.row;

Then add a UITapGestureRecognizer on each image and label, like so

    UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self 
                                                                                 action:@selector(handleTap:)];
    [label addGestureRecognizer:recognizer];
    [imageView addGestureRecognizer:recognizer];
}

- (void) handleTap:(UITapGestureRecognizer*)recognizer
{
    UIView *view = recognizer.view;
    int row = view.tag;
    if ([view isKindOfClass:[UILabel class]]) {
        //Row is row
        //and the label is pressed
    }

    if ([view isKindOfClass:[UIImageView class]]) {
        //Row is row
        //and the imageview is pressed
    }
}
Trinitrocresol answered 17/6, 2012 at 11:29 Comment(0)
D
1

Make the image a UIButton. When the button's action is triggered, you know the user tapped the image (cell will NOT be selected). If cell is selected, you know the user tapped somewhere else on the row (including text view or label).

Also, set the button's tag property to, e.g. the cell's row index so you can know which row's image was tapped.

Deluge answered 17/6, 2012 at 12:9 Comment(0)
R
0

you have two option is to implement :- 1--add UITapGestureRecognizer in your "uitableviewcell" and make it point to image view and pass "indexpath" as parameter to selector and make the delegate pass it to tableviewcell

UILabel *label = =[UILabel alloc]init];
label.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =
[[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(labelTap)]     autorelease];
[label addGestureRecognizer:tapGesture];


-(void)labelTap{
[delegate performselector@selector(labeltapped:)withobject:indexpath];
}

2- Second way is to check the sender of DidSelectRowAtIndexPath of type [imageview or label]; but i prefer the first way

Ricarda answered 17/6, 2012 at 11:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.