如何自定义UITableViewCell的背景颜色?

191

我想自定义UITableView中所有UITableViewCells的背景(以及可能的边框)。到目前为止,我没有成功地完成此项自定义工作,因此我只能使用默认的白色背景单元格。

是否有一种方法可以在iPhone SDK中实现此自定义效果?

18个回答

206

这是我发现的最有效的解决此问题的方法:使用willDisplayCell代理方法(当使用cell.textLabel.text和/或cell.detailTextLabel.text时,它也会处理文本标签背景的白色颜色):

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { ... }

当调用此委托方法时,单元格的颜色是通过单元格控制的,而不是通过表视图控制,就像使用以下代码一样:

- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { ... }

在单元格委托方法的主体内,添加以下代码以交替设置单元格颜色,或者只需使用函数调用使表格的所有单元格具有相同的颜色。

if (indexPath.row % 2)
{
    [cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
}
else [cell setBackgroundColor:[UIColor clearColor]];

这个解决方案在我的情况下非常有效...


这是一种更加简洁的解决方案。大多数其他解决方案要求对UITableViewCell进行子类化。vlado.grigorov的解决方案对我不起作用。 - Ronnie Liew
的确,这是我所看过的各种WWDC演示中苹果公司自己推荐的方法。 - Mike Weller
很好 - 除非你需要在列表顶部添加新行。这种方法会使所有的添加都具有相同的颜色。刷新可以解决这个问题,但是会浪费不必要的时间。昨天才发现这个问题... - JOM
这似乎很好用,但在使用Core Data时出现了问题。通过NSFetchedResultsController添加的新单元格似乎无法正确调用willDisplayCell方法。我不知道该怎么让它正常工作... - radven
在Swift 2.0中设置背景颜色的等效代码为:cell.backgroundColor = UIColor.clearColor - kbpontius

197

您需要将单元格的contentView的backgroundColor设置为您的颜色。如果使用了附件(如披露箭头等),它们将显示为白色,因此您可能需要制作自定义版本。


110
myCell.contentView.backgroundColor = [UIColor greenColor]; - JoBu1324
1
vlado.grigorov的回答更加灵活 - 请参考William Denniss的回答。 - JoBu1324
3
有没有关于如何自己创建UITableViewCellAccessoryCheckmark的链接可以提供?谢谢。 - Dan Rosenstark
6
有时要查看它,您需要设置:cell.textLabel.backgroundColor = [UIColor clearColor]; - Evan Moran

105

这很简单,在iOS 3.0及以上版本,只需在willDisplayCell方法中设置单元格的背景色即可。

不要在cellForRowAtIndexPath方法中设置颜色。

这适用于普通样式和分组样式:

代码:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColor = [UIColor redColor];
}

P.S:以下为willDisplayCell的文档摘录:

"当表格视图使用单元格绘制一行之前,它会向其委托发送此消息,从而允许委托在显示之前自定义单元格对象。该方法给予委托机会覆盖表格视图先前设置的基于状态的属性,如选中和背景颜色。委托返回后,表格视图仅设置alpha和frame属性,仅在动画行滑入或滑出时设置。"

我在这篇来自colionel的帖子中找到了这些信息。感谢他!


3
如果你有一个披露指示器,即使你什么都不用做,这也应该被标记为正确答案。 - Ashish Awaghad
1
如果你想要表格视图背景的不同单元格背景颜色,这种方法就不适用了。 - Chris
对于分组单元格,您可以在cellForRow上进行设置。 - user4234

59

到目前为止,我所发现的最好方法是设置单元格的背景视图并清除单元格子视图的背景。当然,这只适用于带有索引样式的表格,在具有或不具有附件的情况下都能看起来很好。

这里是一个示例,其中单元格的背景被涂成了黄色:

UIView *backgroundView = [ [ [ UIView alloc ] initWithFrame:CGRectZero ] autorelease ];
backgroundView.backgroundColor = [ UIColor yellowColor ];
cell.backgroundView = backgroundView;
for ( UIView *view in cell.contentView.subviews ) 
{
    view.backgroundColor = [ UIColor clearColor ];
}

1
如果您这样做,请确保将opaque属性也设置为NO。 - Lily Ballard
11
使用透明的单元格控件并不推荐。这会严重影响滚动性能,这也是为什么苹果公司总是建议使用不透明的控件。 - Mike Weller
3
在 iOS 4.2 及更高版本中,似乎不再需要这个循环了。 - Frank Schmitt
非常好。使用附属视图时完美运作!! - RyanG

19

将以下代码放置于你的UITableView代理类文件 (.m) 中:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell  forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UIColor *color = ((indexPath.row % 2) == 0) ? [UIColor colorWithRed:255.0/255 green:255.0/255 blue:145.0/255 alpha:1] : [UIColor clearColor];
    cell.backgroundColor = color;
}

7

我同意Seba的观点,我试图在rowForIndexPath委托方法中设置我的交替行颜色,但在3.2和4.2之间结果不一致。以下对我非常有效。

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if ((indexPath.row % 2) == 1) {
        cell.backgroundColor = UIColorFromRGB(0xEDEDED);
        cell.textLabel.backgroundColor = UIColorFromRGB(0xEDEDED);
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }
    else
    {
        cell.backgroundColor = [UIColor whiteColor];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }

}

1
仍然不明白为什么在willDisplayCell中设置它会有任何区别。无论我们是否实现它,它都会被调用,对吗? - user4234

6

尝试了各种不同的解决方案后,以下方法是最优雅的方法。 在以下委托方法中更改颜色:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (...){
        cell.backgroundColor = [UIColor blueColor];
    } else {
        cell.backgroundColor = [UIColor whiteColor];
    }
}

4

vlado.grigorov提供了一些好的建议 - 最好的方法是创建一个背景视图,为其设置颜色,将其他所有东西都设置为clearColor。此外,我认为这种方式是正确清除颜色的唯一方式(尝试他的示例 - 但将'yellowColor'改为'clearColor'),这也是我试图做的。


这种方法的优点是您可以在Interface Builder中将颜色保留为设计时属性。这减少了需要开发人员交互的设计问题。 - whitneyland
1
cell.backgroundView = [[[UIView alloc] initWithFrame: cell.bounds ] autorelease]; cell.backgroundView.backgroundColor = [UIColor redColor]; 单元格.背景视图 = [[[UIView alloc] initWithFrame: 单元格.bounds ] autorelease]; 单元格.背景视图.backgroundColor = [UIColor redColor]; - Brian

3
创建一个视图并将其设置为单元格的背景视图。
UIView *lab = [[UIView alloc] initWithFrame:cell.frame];
            [lab setBackgroundColor:[UIColor grayColor]];
            cell.backgroundView = lab;
            [lab release];

3
为了扩展N.Berendt的回答 - 如果你想根据单元格数据对象中的某个状态设置单元格颜色,通常是在配置表格单元格的其余信息时(即在cellForRowAtIndexPath方法中),你可以通过重写willDisplayCell方法来从内容视图背景颜色设置单元格背景颜色 - 这样可以解决披露按钮背景等不正确的问题,但仍然可以让您在cellForRowAtIndexPath方法中控制颜色,该方法可用于所有其他单元格自定义。
因此: 如果您将此方法添加到您的表视图委托中:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColor = cell.contentView.backgroundColor;
}

然后在你的cellForRowAtIndexPath方法中可以这样写:

if (myCellDataObject.hasSomeStateThatMeansItShouldShowAsBlue) {
    cell.contentView.backgroundColor = [UIColor blueColor];
}

这样做可以避免在willDisplayCell方法中重新获取数据对象,同时也避免了在表格单元进行定制/自定义的两个位置 - 所有的自定义可以放在cellForRowAtIndexPath方法中。


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