Unable to change background color of static table view cell on iOS 7 (iPad)

18,863

Solution 1

Do this:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
     UIImage *pattern = [UIImage imageNamed:@"image.png"];
     [cell setBackgroundColor:[UIColor colorWithPatternImage:pattern]];  
}

Work for me on IOS7

Solution 2

According to Apple's doc:

Whether you use a predefined or custom cell, you can change the cell’s background using the backgroundView property or by changing the inherited backgroundColor property. In iOS 7, cells have a white background by default; in earlier versions of iOS, cells inherit the background color of the enclosing table view. If you want to change the background color of a cell, do so in the tableView:willDisplayCell:forRowAtIndexPath: method of your table view delegate.

So no matter what color you set in tableView:cellForRowAtIndexPath:, iOS 7 changes it to white later. Just set it in tableView:willDisplayCell:forRowAtIndexPath:. Worked for me perfectly.

Solution 3

The only way I could fix this problem was to make the table programmatically instead of using the storyboard. For reference I will post my solution, I hope it can help anyone.

I replaced the uitableviewcontroller for a uiviewcontroller.

then added this:

the header file

#import <UIKit/UIKit.h>

@interface LtHomeViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *mFiles;
NSArray *mPics;
}

@end

And the module file

#import "LtHomeViewController.h"
#import "LtHomeToolbar.h"
#import "LtHomeCustomCell.h"

@interface LtHomeViewController () <LtHomeToolbarDelegate>

@end

@implementation LtHomeViewController
{
LtHomeToolbar *mainToolbar;
UITableView *theListView;
}

#define TOOLBAR_HEIGHT 64.0f

-(UIStatusBarStyle)preferredStatusBarStyle{
 return UIStatusBarStyleLightContent;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
    // Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

CGRect toolbarRect = self.view.bounds; // View controller's view bounds
toolbarRect.size.height = TOOLBAR_HEIGHT;

mainToolbar = [[LtHomeToolbar alloc] initWithFrame:toolbarRect]; // At top
mainToolbar.delegate = self;

[self.view addSubview:mainToolbar];

//
mFiles = [[NSArray alloc] initWithObjects:@"../Lumina.app/lumina0.pdf", @"../Lumina.app/lumina8.pdf", @"../Lumina.app/lumina9.pdf", @"../Lumina.app/lumina10.pdf", nil];
mPics = [[NSArray alloc] initWithObjects:@"vol0.jpg", @"vol8.jpg", @"vol9.jpg", @"vol10.jpg", nil];
//
CGRect tableViewFrame = self.view.bounds;
tableViewFrame.origin.y = TOOLBAR_HEIGHT;
tableViewFrame.size.height = self.view.bounds.size.height - TOOLBAR_HEIGHT;

theListView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStylePlain];
theListView.delegate = self;
theListView.dataSource = self;

theListView.backgroundColor = [UIColor colorWithRed:(116/255.0) green:(167/255.0) blue:(179/255.0) alpha:1.0];


[self.view addSubview:theListView];
}

#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
{
   return 1;
}

- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
{
   return [mFiles count];
}

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   static NSString *cellIdentifier = @"HomeCell";

   // Similar to UITableViewCell, but
   LtHomeCustomCell *cell = (LtHomeCustomCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
  if (cell == nil) {
    cell = [[LtHomeCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
  }

cell.image.image = [UIImage imageNamed:[mPics objectAtIndex:indexPath.row]];

NSString *magName = [[mFiles objectAtIndex:indexPath.row]stringByReplacingOccurrencesOfString:@"../Lumina.app/" withString:@""];
magName = [magName stringByReplacingOccurrencesOfString:@"lumina" withString:@""];
magName = [magName stringByReplacingOccurrencesOfString:@".pdf" withString:@""];
magName = [[@"Triathlon LUMINA " stringByAppendingString:magName]stringByAppendingString:@"号"];

cell.descriptionLabel.text = magName;

return cell;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor colorWithRed:(116/255.0) green:(167/255.0) blue:(179/255.0) alpha:1.0];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 110;
}

#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}


@end

Now I don't know if only this line will help you but as I need more things I took the approach of making the table manually

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    cell.backgroundColor = [UIColor colorWithRed:(116/255.0) green:(167/255.0) blue:(179/255.0) alpha:1.0];
}

David

Solution 4

There is a much easier way to override the cell background color. Subclass UITableViewCell and set it as the class for the static tableview cell. Then override:

-(void) willMoveToSuperview:(UIView *)newSuperview  {
    self.backgroundColor = [UIColor ...];
}

where [UIColor ...] = whatever color you want (e.g. [UIColor clearColor] etc);

Solution 5

Change the ContentView background color instead and it will work.

Share:
18,863
Kovasandra
Author by

Kovasandra

Updated on June 02, 2022

Comments

  • Kovasandra
    Kovasandra almost 2 years

    I am unable to change the background color of static UITableViewCells on iOS 7, when running on iPad device. You can easily check this with following setup:

    • Make a new universal project in Xcode 5 with two storyboards.
    • In each storyboard, put only one controller - table view controller, and set it as the initial one.
    • Put a few (e.g. 3) static cells in the table view in both controllers/storyboards.
    • Set the background color of each static cell to different colors in Interface Builder (I use red, green, and clear colors).

    Now, run the app on iPhone and iPad simulators (iOS 7).

    On the iPhone simulator, everything is ok;
    while on the iPad simulator, all cells are colored white.

    I tried to force iPad to work correctly by setting runtime properties in Interface Builder for cells:

    • backgroundColor to clear color
    • contentView.backgroundColor to clear color
    • backgroundView to nil

    but nothing helps. Actually, setting the runtime property of contentView.backgroundColor will change the cell color, but it does not work with clear color (which means there is another view colored in white behind it).

    It is very strange that two devices on same version of iOS produce different results. Can anyone else confirm this bug?

    Does anyone have a solution to this problem, or the only way is to go for dynamic properties + setting color in cellForRowAtIndexPath? I would like to use static cells, because the nature of the problem is static.

    p.s. I just realized that I forgot to try to set the backgroundView.backgroundColor runtime property to clear color, and I don't have access to a Mac at the moment. Maybe that would do the trick.

  • Kovasandra
    Kovasandra over 10 years
    You probably don't need willDisplayCell delegate method. You could achieve same by moving the code from that method into cellForRowAtIndexPath. But my question was about static cells.I would like to avoid using dynamic prototypes/cells generated in code.
  • David
    David over 10 years
    Yes actually you are right, I figure it out right after I posted this answer. As for your problem would not work if you use the cellForRowAtIndexPath function and just filter the static cell using the indexPath.row? you can then just make a if cycle or a switch and change the background color of the individual cells.
  • Kovasandra
    Kovasandra over 10 years
    I don't think you can use datasource when you are using static cells :) Static cells are meant to be built in IB with "What you see is what you get" principle in mind. It is very convenient to use them when your screen has fixed number of options. After that you can easily assign segues to those static cells, or even put container views in them separating your screen into modules, where each module is controlled by separate child view controller. This greatly improves reusability of your code.
  • David
    David over 10 years
    well then you got a tough one, sorry, Apple did however rollout a new update during the weekend, I moved on from storyboards so I cannot verify if it did change anything (that I don't think so anyway), good luck with that and please update if you do find a solution.
  • holex
    holex over 10 years
    ...and that method would be the proper place to finalise a cell in runtime since iOS2.
  • Kovasandra
    Kovasandra over 10 years
    Yes, iOS docs says that default color of cell is white. But that does not mean we should not be able to change that color in IB. Also, as I already mentioned, you can change it in IB for iPhone devices, but not for iPad devices. That is clearly a bug if you ask me :) One last thing - we already discussed your solution. It works for dynamic cells, but not for static ones, since you should not have datasource when using static cells (which means cellForRowAtIntexPath datasource method should not be implemented).
  • Kovasandra
    Kovasandra over 10 years
    This is only solution that works for now. I was hoping to find solution in IB (without any code, as we could do before iOS7), but seems there is no such solution at the moment, and we will have to wait for Apple to fix this. I will accept this solution even it is not exactly what I was searching for, as a temporary workaround. But I want to add few warnings: if you use this solution with static cells, you have to subclass UITableViewController and override ONLY delegate methods (in this case willDisplayCell). You should not override datasource methods when using static cells.
  • Kovasandra
    Kovasandra over 10 years
    You can't use standard UIViewController with table embedded in it, because static cells require UITableViewController in order to work properly.
  • Kovasandra
    Kovasandra over 10 years
    So, long story short: subclass UITableViewController, override only willDisplayCell delegate method, inside that method set cell background color to clear color (or whatever color you want), and finally set class of controller in IB to your new subclass of UITableViewController.
  • Kovasandra
    Kovasandra over 10 years
    After thinking for a while, you could probably implement cellForRowAtIndexPath even for static cells, but you would need to call super implementation of same method in order to get static cell you defined in storyboard from UITableViewController implementation. So, for example you could do: UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; cell.backgroundColor = [UIColor clearColor]; return cell; Even if this works, I am not fan of this solution, and would preffer doing it in willDisplayCell delegate method.
  • David
    David over 10 years
    I'm sorry @Kovasandra, but you do realise that is the same answer I gave you earlier right?
  • Kovasandra
    Kovasandra over 10 years
    Yes I do, but you went for programatic solutions all the way (with datasource, delegate and dynamic cells) :) I don't like this solution either, because there should be way to do it in IB. I accepted it just because there is no IB solution at the moment. I did up vote your answer though, but seems someone else also down voted it :)
  • Kovasandra
    Kovasandra over 10 years
    I think the last line of quoted text from docs was not there when this question was posted. They probably added it recently.I got informed by Apple through the Bug Reporter that they are aware of the issue. I am not the first who reported it to them (My issue was duplicate of another issue that is still not solved). I assume they added above line into documentation to give people programatic solution to this problem before they fix IB issue.It just does not make sense that you can't override cell background colour in IB. Default colour should be just that-default if you don't set other value.
  • Jano
    Jano almost 10 years
    The datasource will be ignored if you use static cells. From Apple´s Table View Programming Guide for iOS: “If a table view in a storyboard is static, the custom subclass of UITableViewController that contains the table view should not implement the data source protocol.” This answer is the right one.
  • crishoj
    crishoj almost 10 years
    The behaviour is incredibly inconsistent at best: Background colour from IB appears on iPhones, but not on iPads. Resorting to programatically setting backgroundColor in tableView:willDisplayCell:forRowAtIndexPath: is nothing short of an ugly hack.
  • jkoreska
    jkoreska over 9 years
    I prefer this if I'm already subclassing - keeps the concerns with the cell. Still a bug tho, shouldn't need this code!
  • Pang
    Pang almost 9 years
    Note, however, that the content view does not include the area under the accessory view.