8

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

目前有

- (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 中的按钮),但这至少是正确的方法吗?

4

5 回答 5

19

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

一些提示:

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

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

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

  • 除了通过添加按钮addSubview,您可以将其作为accessoryView单元格的按钮返回,这样您就不必担心定位它(除非您已经将附件视图用于其他用途——例如显示按钮)。

于 2009-07-02T22:23:56.963 回答
7

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

下面的代码创建了一个可重用的单元格(以通常的方式)。提到的两个图像(“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;
于 2010-12-27T13:36:53.610 回答
1

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

小费:

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

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

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

于 2009-07-02T21:41:38.703 回答
1

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

查看Apple 指南以获取更多信息。

于 2009-07-02T21:48:25.193 回答
0

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

于 2011-01-20T22:11:50.413 回答