UITableView 单元格中的 UIButton,例如“删除事件”

Posted

技术标签:

【中文标题】UITableView 单元格中的 UIButton,例如“删除事件”【英文标题】:UIButton in UITableView cell like "Delete Event" 【发布时间】:2009-07-02 21:32:01 【问题描述】:

我想在表格单元格中添加一个按钮。日历应用中的“删除事件”启发了我……(类似情况是联系人中的“共享联系人”)

目前有

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
  //..yadayadayada
  cell = [tableView dequeueReusableCellWithIdentifier:@"buttonCell"];
  if (cell == nil) 
    cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"buttonCell"] autorelease];
  
  UIButton *button = [UIButton buttonWithType:UIButtonTypeInfoDark];
  [button setBackgroundColor:[UIColor redColor]];
  button.titleLabel.text = @"Foo Bar";
  [cell.contentView addSubview:button];

确实会产生一个按钮。它看起来还不是它应该的样子(很明显我从来没有处理过 iPhone 中的按钮),但这至少是正确的方法吗?

【问题讨论】:

按钮的最终操作会根据它所在的行而有所不同吗? (例如,通过电子邮件发送此行中的当前联系人等...) 如果是,您可以将每个单元格按钮的标签设置为 indexPath 行,然后在触摸执行的选择器中读取发送者的标签。 好吧,就像“删除事件”一样,我在 UI 底部(即最后一行)只有一个按钮。 【参考方案1】:

现在每次显示单元格时,您都在分配一个按钮、设置其值并将其添加到单元格的 contentView 中。当单元格被重用时(通过dequeueReusableCellWithIdentifier),您将创建 another 新按钮,将其添加到单元格中(在旧按钮之上)等等。事实上它已经通过 @987654322 @ 但没有明确的释放意味着每个按钮的保留计数永远不会变为零,所以它们都会留下来。在上下滚动一段时间后,单元格最终会出现数百个按钮子视图,这可能不是您想要的。

一些提示:

永远不要在 cellForRowAtIndexPath 调用中分配东西,除非它在 ​​dequeueReusableCellWithIdentifier 返回 nil 并且您正在初始化单元格时完成。在所有其他后续时间,您将收到已设置的缓存单元格,因此您所要做的就是更改标签或图标。您将希望在单元格分配代码之后将所有按钮分配内容移到 if 条件中。

按钮需要有一个位置和一个目标设置,以便在点击时它会做一些事情。如果每个单元格都有这个按钮,一个巧妙的技巧是让它们都指向同一个目标方法,但将按钮的tag 值设置为单元格的indexPath.row(在单元格分配块之外,因为每个单元格都不同细胞)。按钮的常见点击处理程序将使用发送者的标记值来查找数据源列表中的基础数据。

在完成addSubview 之后,请在按钮上调用release。这样,保留计数将降至零,并且当父对象被释放时,对象实际上会被释放。

您可以将其作为单元格的accessoryView 返回,而不是通过addSubview 添加按钮,这样您就不必担心定位它(除非您已经在使用accessoryView else -- 比如披露按钮)。

【讨论】:

非常感谢您提供宝贵的提示和解释。像我这样的 iPhone 编程新手肯定会欣赏这一点。至于技巧 4,与“删除事件”/“共享联系人”一样,我在 UI 底部(即最后一行)只有一个按钮。所以,它不能是附件视图,但它必须填满整行。我还在为此苦苦挣扎。 关于#3,释放按钮会使你的应用程序崩溃。他没有分配它。【参考方案2】:

我采用了不同的方法来创建与日历应用程序中的“删除事件”按钮等效的按钮。我没有将按钮添加为子视图,而是向单元格添加了两个背景视图(红色和深红色,具有漂亮的渐变),然后将角修圆并将边框设置为灰色。

下面的代码创建了一个可重复使用的单元格(以通常的方式)。提到的两个图像(“redUp.png”和“redDown.png”)取自日历的“删除事件”按钮的屏幕截图。 (这似乎比以编程方式创建渐变要快。)还有一些微调的余地,让它更接近日历的“删除事件”外观,但这已经非常接近了。

按钮的动作由tableView委托方法tableView:didSelectRowAtIndexPath:方法触发。

// create a button from a table row like the Calendar's 'Delete Event' button
// remember to have an #import <QuartzCore/QuartzCore.h> some above this code

static NSString *CellWithButtonIdentifier = @"CellWithButton";

 UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:CellWithButtonIdentifier];
 if (cell == nil) 
  cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellWithButtonIdentifier] autorelease];
  [[cell textLabel] setTextAlignment: UITextAlignmentCenter];

  UIImageView* upImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"redUp.png"]];
  UIImageView* downImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"redDown.png"]];

  [cell setBackgroundView: upImage];
  [cell setSelectedBackgroundView: downImage];

  [[upImage layer] setCornerRadius:8.0f];
  [[upImage layer] setMasksToBounds:YES];
  [[upImage layer] setBorderWidth:1.0f];
  [[upImage layer] setBorderColor: [[UIColor grayColor] CGColor]];

  [[downImage layer] setCornerRadius:8.0f];
  [[downImage layer] setMasksToBounds:YES];
  [[downImage layer] setBorderWidth:1.0f];
  [[downImage layer] setBorderColor: [[UIColor grayColor] CGColor]];

  [[cell textLabel] setTextColor: [UIColor whiteColor]];
  [[cell textLabel] setBackgroundColor:[UIColor clearColor]];
  [cell  setBackgroundColor:[UIColor clearColor]]; // needed for 3.2 (not needed for later ios versions)
  [[cell textLabel] setFont:[UIFont boldSystemFontOfSize:20.0]];

  [upImage release];
  [downImage release];
 
 return cell;

【讨论】:

您应该在代码中添加[cell.textLabel setShadowColor:[UIColor blackColor]]; [cell.textLabel setShadowOffset:CGSizeMake(0, -1)];。这使文本具有轻微的浮雕效果,因此它看起来更像原生按钮。【参考方案3】:

是的,这通常是正确的方法。

提示:

为您的按钮事件设置回调,以便在单击时实际执行某些操作。

[myButton addTarget:self action:@selector(whatMyButtonShouldDo:)   
  forControlEvents:UIControlEventTouchUpInside];

编辑:调整了使用系统按钮的代码,这使得我编写的很多内容变得不必要。

【讨论】:

在他的示例代码中,不需要释放按钮,因为 [UIButton buttonWithType:] 返回一个自动释放的实例。 你说得完全正确,我是从 I 使用 initWithFrame 的代码中复制的。调整。 感谢您的反馈。记录了发布/自动释放的提示。真的有必要摆弄框架吗?我只是想让按钮填满整个表格单元格(即不用担心位置和大小); “删除事件”很好地证明了这一点。 是的,我通过复制我的代码让事情变得太复杂了,我不使用系统按钮,我手动设置了框架和背景图像。我大大缩短了我的答案。【参考方案4】:

是的,你在正确的轨道上,这是向单元格添加子视图的最简单方法(另一种是子类化 UITableViewCell)。

查看Apple guide 了解更多信息。

【讨论】:

【参考方案5】:

为避免定位和内存管理麻烦,您可以创建一个专门的单元类并链接到 XIB。这听起来对我来说是最干净的方法。链接在这里: http://icodeblog.com/2009/05/24/custom-uitableviewcell-using-interface-builder/

【讨论】:

以上是关于UITableView 单元格中的 UIButton,例如“删除事件”的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 单元格中的 UITextField 以编程方式成为FirstResponder

重用 uitableview 单元格以及单元格中的子视图

更新 UITableView 单元格中的特定按钮图像

滚动 UITableView 时自定义单元格中的 UITextField 文本正在更改

单元格中的 UITableView 动画导致平滑滚动中断

UITableView 自定义单元格中的 UIButton 触摸无法正常工作