简体   繁体   中英

UIButton inside UITableViewCell steals touch from UITableView

I have a problem similar to this one but answer provided there doesn't help much. I have UITableView with some custom UITableViewCells , those cells have some nested custom UIViews and finally some UIButtons inside. The problem, as in question specified above, is that when I touch my button touch event won't populate to UITableView and it never scrolls.

Here's some code (it's just fastest way to reproduce, it's not my actual code):

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

@property (strong, nonatomic) IBOutlet UITableView * tableView;

@end

@implementation ViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
    {
        self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0,
                                                                       self.view.bounds.size.width,
                                                                       self.view.bounds.size.height)
                                                      style:UITableViewStylePlain];
        [self.view addSubview:self.tableView];
        self.tableView.delegate = self;
        self.tableView.dataSource = self;
    }
    return self;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 1;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell * cell = [[UITableViewCell alloc] init];
    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.backgroundColor = [UIColor redColor];
    button.frame = CGRectMake(0, 0, 50, 44);
    [cell.contentView addSubview:button];
    return cell;
}

@end

Red button in the only cell won't let table view to bounce scroll.

Can anyone help me a bit?

PS Don't pay attention to the stupidity of the code I've provided, I'm aware of all issues about it. I just provided it to show what the issue is all about. It's the conflict of buttonView and scrollView .

You can change the behaviour by overriding touchesShouldCancelInContentView: in the UITableView. For this to work you'll need to replace the table view with this subclass, either in loadView or in your xib file.

@interface AutoCancelTableView: UITableView
@end

@implementation AutoCancelTableView

//
// Overriding touchesShouldCanceInContentView changes the behaviour
// of button selection in a table view to act like cell selection -
// dragging while clicking a button will cancel the click and allow
// the scrolling to occur
//
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
    return YES;
}

@end

This is the standard behaviour of UIScrollView which tableviews use. The system doesn't know that you want to scroll until you move your finger, but by that time you have already "pressed" on the button and so it assumes that's what you want to do.

You can play with a couple of properties on your tableview's scrollview to change the behaviour, but you may find they negatively impact the feel of your cells and buttons because of added delays.

self.tableView.delaysContentTouches = YES;

delaysContentTouches If the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent...

and

self.tableView.canCancelContentTouches = YES

canCancelContentTouches If the value of this property is YES and a view in the content has begun tracking a finger touching it, and if the user drags the finger enough to initiate a scroll, the view receives a touchesCancelled:withEvent: message and the scroll view handles the touch as a scroll.

Because all the above answers not working for me. I add a imageView on the button and make the imageView user interface YES, then add a tap gesture on the iamgeView. In the tap gesture related methods I put the button related methods in. so all is well.. may be hack. But it work well..

Below code works for me:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cell = [tableView dequeueReusableCellWithIdentifier:@"cell_id"];
cell.userInteractionEnabled = YES;
if (cell == nil) {
    cell = [[[CustomCell1 alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell_id"]autorelease];
}

[cell.button addTarget:self action:@selector(button_action) forControlEvents:UIControlEventTouchUpInside];}

-(void)button_action{NSLog(@"Hello!");}

This is my custom cell:

#import "CustomCell.h"
@implementation CustomCell
@synthesize button;


- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
    button = [[UIButton alloc]init];
    button =[UIColor redColor];
    [self.contentView addSubview: button];
           }
return self;}

- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+50 ,+15, 100, 100);
        button = frame;}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{   [super setSelected:selected animated:animated];
// Configure the view for the selected state
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM