UITableViewCell 中的 UIButton 抢占了 UITableView 的触摸事件

11

我有一个类似于这个的问题,但是那里提供的答案并没有帮助太多。

我有一个包含一些自定义UITableViewCellsUITableView,这些单元格中有一些嵌套的自定义UIViews和最后一些内部的UIButtons。就像上面提到的问题那样,当我触摸我的按钮时,触摸事件不会传播到UITableView且它永远无法滚动。

下面是一些代码 (这只是最快的复制方式,不是我的实际代码):

@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

只有一个单元格中的红色按钮会阻止表视图进行弹性滚动。

有人可以帮我一下吗?

P.S. 不要注意我提供的代码的愚蠢,我知道它的所有问题。我只是提供它来展示问题所在。这是和之间的冲突。

4个回答

13

你可以通过在UITableView中重写touchesShouldCancelInContentView:来更改其行为。为了使其起作用,你需要在loadView或者xib文件中使用这个子类替换原有的 table view。

@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

谢谢你!现在表格视图页脚中的单元格和按钮的行为完全相同... ;) - Trenskow
可以确认这个有效。只需确保将其与 tableView.delaysContentTouches = false 结合使用即可。 - mxcl

10

这是UIScrollView的标准行为,它被表格视图使用。系统在您移动手指之前不知道您想要滚动,但此时您已经按下了按钮,因此系统会认为您想做的就是那个操作。

您可以在表格视图的滚动视图上设置一些属性来更改其行为,但可能会因为增加的延迟而对单元格和按钮的感觉产生负面影响。

self.tableView.delaysContentTouches = YES;

delaysContentTouches 如果此属性的值为 YES,则滚动视图将延迟处理触摸按下手势,直到确定滚动是意图...

and

self.tableView.canCancelContentTouches = YES

canCancelContentTouches 如果这个属性的值为YES,并且内容中的一个视图已经开始追踪一个手指的触摸,如果用户拖动手指足够来启动滚动,则该视图会接收一个 touchesCancelled:withEvent: 消息,滚动视图会将触摸作为滚动处理。


8
我仍然不能让这个功能适用于UITableView内部的UIControl。另外,由于UITableViewUIScrollView的子类,你的代码应该是 self.tableView.canCancelContentTouches = YES; - johnboiles
1
@johnboiles 你应该设置 elf.tableView.scrollView.delaysContentTouches = NO; - passol
这里显示的组合不起作用。@johnboiles是正确的。对我刚刚起作用的是:mytable.delaysContentTouches = false和mytable.canCancelContentTouches = true。这使得单元格内部的按钮像正常情况下一样工作。 - zumzum

1

因为以上所有的答案对我都不起作用。我在按钮上添加了一个imageView,并将imageView的用户界面设置为YES,然后在imageView上添加了一个tap手势。在tap手势相关方法中,我放置了与按钮相关的方法。所以一切都很好。可能是hack,但它很有效。


0
以下代码对我有效:

 - (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!");}

这是我的自定义单元格:

#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
}

好的,对我来说并没有用 - 触摸按钮仍然会阻止滚动tableView。无论如何还是谢谢。 - DemoniacDeath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接