简体   繁体   中英

iOS: Using UIAppearance to define custom UITableViewCell color

If I set the backgroundColor attribute on a grouped UITableViewCell, the background color successfully changes. Great.

But I'd like to use UIAppearance to change the background color on all my UITableViewCells, so I can do it in one place and affect a change everywhere. Here's my code:

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

UITableViewCell implements UIAppearance and UIAppearanceContainer, so I would have thought this would work. But it doesn't. I've also tried using -[UITableViewCell appearanceWhenContainedIn:(Class)] , and that doesn't work either.

Any ideas?

Update (2013/7/8) - This has been fixed in newer versions of iOS. However, it's worth knowing about if you're targeting iOS 6 or below.

You can blame Apple for this one, and it's actually pretty mean of them. Technically , backgroundColor is not customizable through appearance proxies.

From Apple's documentation:

To support appearance customization, a class must conform to the UIAppearanceContainer protocol and relevant accessor methods must be marked with UI_APPEARANCE_SELECTOR.

If we go into a class like UIBarButtonItem and look at the tintColor property we see this:

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

So because it's marked with the UI_APPEARANCE_SELECTOR tag we know it works with UIAppearance .

Here's where Apple are particularly mean: in a UIView , backgroundColor has no appearance selector tag, but still works with UIAppearance . According to all the documentation Apple provide it should not, but yet it does!

This gives the misleading impression that it will work for all sub-classes of UIView , including UITableView . This has come up before, in this previous SO answer

So the bottom line is that backgroundColor shouldn't work at all with UIAppearance , but for some reason it does on a UIView . It is not guaranteed to work on UIView subclasses, and it doesn't work at all on UITableView . Sorry I couldn't give you a more positive answer!

You can create your own subclass of UITableViewCell that conforms to UIAppearance and mark a custom setter with UI_APPEARANCE_SELECTOR. Then set the cell backgroundColor on the superlass from your custom setter .

In your appDelegate

[[CustomCell appearance] setBackgroundCellColor:[UIColor redColor]];

In your UItableView subclass

@interface CustomCell : UITableViewCell <UIAppearance>

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

@implementation CustomCell

@synthesize backgroundCellColor;

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

I'm using ARC in this example.

Without Subclassing ! Doing this on a subclass is probably NOT the best practice, especially if you want to hit all tableView backgrounds. That's a lot of subclassing. A lot of potential bugs. A mess really. The best way to do this is to use a category. You will have to set one up for both the tableViewCell and the tableView. I will just demonstrate the one for the cell. The property on the tableView you must do is the backgroundColor property. NB. I'm prepending my methods with "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

Now in your appDelegate or some manager class you'll import the category and just call it as if it had an appearance proxy built in.

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

Ok, so now just do the one for the tableView's background property. Simple.

I used category for this. Below is the sample code In your .h file write

*@interface UITableViewCell (MyCustomCell)
@property (nonatomic, weak) UIColor *backgroundCellColor UI_APPEARANCE_SELECTOR;
@end*

In your .m file write

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

It worked well for me. :) Thanks Nate!!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM