iOS:使用UIAppearance自定义UITableViewCell颜色

22

如果我在一个分组的UITableViewCell上设置了backgroundColor属性,背景色会成功更改。很好。

但是我想使用UIAppearance在所有的UITableViewCells中更改背景色,因此我可以在一个地方执行更改并影响到每个地方。以下是我的代码:

[[UITableViewCell appearance] setBackgroundColor:[UIColor colorWithRed:30.0/255.0 green:30.0/255.0 blue:30.0/255.0 alpha:1.0]];

UITableViewCell实现了UIAppearance和UIAppearanceContainer,因此我本以为这会起作用。但是它没有。我还尝试使用-[UITableViewCell appearanceWhenContainedIn:(Class)],但也没有起作用。

有什么想法吗?

4个回答

42

更新(2013/7/8)- 这已经在较新版本的iOS中得到了修复。但是,如果您的目标是针对iOS 6或更低版本,请了解这一点。

您可以归咎于苹果公司,他们实际上非常卑鄙。从技术上讲,backgroundColor 不能通过外观代理自定义

来自苹果文档:

为了支持外观自定义,类必须符合UIAppearanceContainer协议,并且相关的访问器方法必须标记为UI_APPEARANCE_SELECTOR。

如果我们进入像UIBarButtonItem这样的类并查看tintColor属性,我们会看到这个:

@property(nonatomic,retain) UIColor *tintColor UI_APPEARANCE_SELECTOR;

因为它带有UI_APPEARANCE_SELECTOR标签,所以我们知道它可以与UIAppearance一起使用。

这是苹果特别无情的地方:在UIView中,backgroundColor没有外观选择器标签,但仍然可以与UIAppearance一起使用。根据苹果提供的所有文档,它不应该这样做,但它确实这样做了!

这会给人留下错误印象,认为它将适用于UIView的所有子类,包括UITableView。这以前已经出现过,在这个之前的SO答案中

因此,关键问题是backgroundColor根本不应该与UIAppearance一起工作,但由于某种原因,在UIView上确实可以。不能保证它适用于UIView子类,并且在UITableView上根本不起作用。抱歉我无法给您一个更积极的答案!


谢谢你的解释。如果没有你,我可能会因为这个问题而在墙上摇头几个小时。 - matsr
如果这是真的让你很困扰(我也很困扰!),一定要向苹果公司提交错误报告。我不认为这真的是一个“bug”,但它肯定是一个缺陷。我甚至认为我曾经看到过苹果公司的某个人在外观代理上使用setBackgroundColor来进行代码演示。 - lxt
@lxt:我正在研究iOS 7,但似乎没有被修复。你能否给我发送一封电子邮件(我的电子邮件地址在信头中),以便讨论。我知道iOS 7仍然受到NDA的限制,所以在信息可用之前,你不想在这里公开任何信息。 - Victor Ronin
@VictorRonin - 你在看UITableViewCell的头文件吗? - lxt
@lxt:是的。而且只有一件事被UI_APPEARANCE_SELECTOR标记(它不是背景)。 - Victor Ronin
你可以使用一个类别(category)来添加UI_APPEARANCE_SELECTOR,但最好不要这样做。因为UITableviewCells被用于可能会让你感到惊讶的控件上,例如选择器!我已经有这样的经历了。 - SmileBot

17
你可以创建一个继承自UITableViewCell并符合UIAppearance的子类,并使用UI_APPEARANCE_SELECTOR标记自定义setter。然后从你的自定义setter设置超类的cell backgroundColor。
在你的appDelegate中。
[[CustomCell appearance] setBackgroundCellColor:[UIColor redColor]];

在你的UITableView子类中

@interface CustomCell : UITableViewCell <UIAppearance>

@property (nonatomic, weak) UIColor *backgroundCellColor UI_APPEARANCE_SELECTOR;

@implementation CustomCell

@synthesize backgroundCellColor;

-(void)setBackgroundCellColor:(UIColor *)backgroundColor
{
    [super setBackgroundColor:backgroundColor];
}

在这个例子中,我正在使用ARC。


即使没有子类化,您也可以使用分类和自定义属性来代理外观调用。如果您想要为无法使用子类化的部分(例如 UIPrintInteractionController)设置主题,这可能会很有用。 - Tom

3
不需要子类化 在子类上执行此操作可能不是最佳实践,特别是如果您想要涵盖所有tableView背景。这需要很多子类化,有很多潜在的错误。真正的混乱。最好的方法是使用分类。您必须为tableViewCell和tableView都设置一个分类。我将仅演示用于单元格的分类。您必须对tableView上的backgroundColor属性进行设置。注意:我在我的方法前加“sat”。

// .h

    #import <UIKit/UIKit.h>

@interface UITableViewCell (Appearance)<UIAppearance>
@property (strong, nonatomic) UIColor *satBackgroundColor UI_APPEARANCE_SELECTOR;
@end

// .m

#import "UITableViewCell+Appearance.h"

@implementation UITableViewCell (Appearance)

- (UIColor *)satBackgroundColor
{
    return self.backgroundColor;
}

- (void)setSatBackgroundColor:(UIColor *)satBackgroundColor
{
    self.backgroundColor = satBackgroundColor;
}


@end

现在,在您的appDelegate或某个管理类中,您将导入该类别,并像内置外观代理一样调用它。

UITableViewCell *cell = [UITableViewCell appearance];
cell.satBackgroundColor = [UIColor orangeColor];

好的,现在只需为tableView的背景属性做一个。简单。


0
我为此使用了类别。以下是示例代码 在您的.h文件中编写
*@interface UITableViewCell (MyCustomCell)
@property (nonatomic, weak) UIColor *backgroundCellColor UI_APPEARANCE_SELECTOR;
@end*

在你的 .m 文件中写入:
*@dynamic backgroundCellColor;
-(void)setBackgroundCellColor:(UIColor *)backgroundColor
{
    [super setBackgroundColor:backgroundColor];
}*

这对我很有效。:) 谢谢Nate!!!


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