如何捕获 UIButton 事件:在自定义 UITableViewCell 实现中添加了 UIButton

Posted

技术标签:

【中文标题】如何捕获 UIButton 事件:在自定义 UITableViewCell 实现中添加了 UIButton【英文标题】:How to catch UIButton events: UIButton added inside custom UITableViewCell implementation 【发布时间】:2012-11-21 15:29:32 【问题描述】:

有一些discussions关于如何在著名的 UITableCellView 中添加 UIButton

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

方法以及如何处理按钮点击。我已经对它们进行了测试,它们或多或少都可以正常工作。

我的设置略有不同。我想添加 UIButton - 实际上我有几个按钮位于不同的 UIImageViews 上 - 在我的自定义 UITableCellView 类中使用滑动触摸隐藏/显示。为简单起见,我们假设只有一个 UIImageView 添加到单元格的视图堆栈中,并且只有一个 UIButton:

这是我的 UITableViewCell 实现的相关部分:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

   self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   if (self) 
     // sub menu
     self.tableCellSubMenu = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320.0, 88.0)];
     [self.tableCellSubMenu setImage:[UIImage imageNamed:@"cell_menu_back"]];
     [self addSubview:self.tableCellSubMenu];

     UIButton *but = [UIButton buttonWithType:UIButtonTypeCustom];                              
     but.frame = CGRectMake(10.0, 0, 77.0, 88.0);
     [but setImage:[UIImage imageNamed:@"cell_menu_icon_plus_up"] forState:UIControlStateNormal];
     [but setImage:[UIImage imageNamed:@"cell_menu_icon_plus_down"] forState:UIControlStateSelected];
     [but setImage:[UIImage imageNamed:@"cell_menu_icon_plus_down"] forState:UIControlStateHighlighted];
     [but addTarget:self action:@selector(tableCellButtonPress:) forControlEvents:UIControlEventTouchUpInside];
     [self.tableCellSubMenu addSubview:but];
     ...
     
   return self;

UIButton 被添加到 UIImageView,而 UIImageView 又被添加到单元格的视图堆栈中。为简单起见,我将按钮的目标配置为“self”。在我的真实设置中,目标是我处理按钮事件的 UITableViewController。我可以保证所有设置都正常工作(例如,通过将 UIImageView 替换为 UIControl,我们稍后会看到)。

不幸的是,在此配置中,按钮上的 touch up inside 事件不会触发。唯一被调用的函数是

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

在控制器中。通常,我将 UIButtons 放在 UIControl 视图上。话虽如此,当我在上面的代码中用 UIControl 替换 UIImageView 时,按钮事件按预期触发,但是,

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

不再被调用。我两个都想要。

如何让它工作?

更新 1:

我在自定义 UITableViewCell 实现中实现了以下方法:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
    CGPoint location = [((UITouch *)[touches anyObject]) locationInView:self];
    if (CGRectContainsPoint(but.frame, location)) 
      [self.touchButtonDelegate tableViewCellButtonTouched:self button:(UIButton*)but indexPath:self.touchButtonIndexPath];
    
    [super touchesBegan:touches withEvent:event];

我仍在使用“UIImageView”对几个按钮进行分组和定位。

self.touchButtonDelegate 是 UITableViewController。 here 提供更完整的解决方案。

【问题讨论】:

尝试将按钮添加到单元格本身,而不是 UIImageView。 当然,这可行,但我需要将按钮添加到某种视图中,以便能够将一组按钮滑出可见区域,例如当用户在表格单元格上滑动以显示子菜单时。 【参考方案1】:

UIImageViews 没有启用用户交互。您应该将其添加到单元格本身或另一个 UIView。

【讨论】:

好的,但是要改用什么样的视图呢?正如我所说,我用 UIControl 和 UIView 替换了 UIImageView。这一切都有效,但是,所有 UITableViewDelegate 方法,例如cellForRowAtIndexPath 方法,不要被调用。 对,两者都不会被调用。由于按钮捕获触摸事件的方式,该按钮正在阻止触摸事件到达单元格。如果您希望两者都发生,您可能需要停止使用 UIButtons,而是使用 touchesBegan: 和 touchesEnded: 方法对您的按钮进行一些点击测试以对两者做出反应。并且不要忘记调用这些方法的 super 实现以保持表格交互正常工作。

以上是关于如何捕获 UIButton 事件:在自定义 UITableViewCell 实现中添加了 UIButton的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义 UIButton 中实现 .isHighlighted 动画?

在自定义 UITableViewCell 中按下 UIButton 时如何获取 indexPathForSelectedRow

如何在自定义 UITableViewCell 中更改 UIButton 标题的权重属性?

如何在自定义变体上捕获数组索引

UIButton 在自定义单元格中更改

UIbutton 在自定义 UITableViewCell 中释放