This seems like an easy problem, but I've hit a brick wall finding a solution and I'm hoping someone on here can help...
I am making a UITableView using UITableViewStyleGrouped, and I am seeing a small (1 pixel) white line between the first and second row of every section of my table view (see image)
It seems that the reason for this line is that the first cell in each section is 1 pixel taller than the others. When I set the initial cell of each group to be 29 pixels high (the others are 30) the gap disappears and all is well.
While this is workaround is successful, I'd rather know the reason for this occurring so I can avoid using a messy hack.
FYI:
Any help is greatly appreciated.
Thanks
Code for table setup:
myTable = [[UITableView alloc] initWithFrame:CGRectMake(TABLE_SHIFT_OFFSET,
DATE_SLIDER_HEIGHT - DATE_SLIDER_SHADOW_HEIGHT,
326,
self.view.frame.size.height - DATE_SLIDER_HEIGHT + DATE_SLIDER_SHADOW_HEIGHT) style:UITableViewStyleGrouped];
myTable.backgroundColor = [UIColor clearColor];
myTable.backgroundView = nil;
myTable.separatorStyle = UITableViewCellSeparatorStyleNone;
[self.view addSubview:myTable];
myTable.dataSource = self;
myTable.delegate = self;
Code for cell setup:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// This is a hack to make sure that a white line doesnt appear between the
// first and second rows in the table, which happens for reasons I dont understand
if (indexPath.row == 0) {
return 29;
}
return 30;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"satCell"];
if (!cell)
{
cell = [[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"satCell"];
}
cell.backgroundView = nil;
cell.backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
cell.backgroundColor = [UIColor whiteColor];
int numberOfRowsInThisSection = [self tableView:tableView numberOfRowsInSection:indexPath.section];
if (numberOfRowsInThisSection == 1)
{
cell.backingImage = self.singleWhite;
}
else if (indexPath.row == 0)
{
cell.backingImage = self.topWhite;
}
else if (indexPath.row % 2 == 0)
{
// Even row
if (indexPath.row == numberOfRowsInThisSection - 1)
{
// Last row (even)
cell.backingImage = self.botWhite;
}
else
{
// Normal row (even)
cell.backingImage = self.midWhite;
}
}
else if (indexPath.row % 2 == 1)
{
// Odd row
if (indexPath.row == numberOfRowsInThisSection - 1)
{
// Last row (even)
cell.backingImage = self.botDark;
}
else
{
// Normal row (odd)
cell.backingImage = self.midDark;
}
}
// Setup cell text [REMOVED FOR BREVITY]
return cell;
}
The code for setting the backing Image within MyTableViewCell:
- (void)setBackingImage:(UIImage *)backingImage
{
if (self.backingImage != backingImage)
{
_backingImage = nil;
_backingImage = backingImage;
self.backingView.image = backingImage;
}
}
self.backingView is set up using the following code:
[[UIImageView alloc] initWithFrame:CGRectMake(7, 0, 307, 30)];
This is kind of a known issue, only happens when you hide the separators of a grouped tableView, the exact same thing happened in this other stack overflow question.
Simply put, the top and lower cells use one extra point, but the separator hides it, so the solution is:
Option 2 seems to be the "cleanest" and adds the benefit of supporting variable heights of tableView cells.
And why does it have that extra point? Only Apple knows.
In my experience, grouped table views add 1 point (not pixel!) to the height of the first and last row in each section. You should be able to see this by adding debug code to override layoutSubviews on your table cell class, have it call super and then print the bounds.size.height.
I presume this is to provide space for the border drawing and, like you, I have just adjusted the value I return for the height of the first and last cells to cancel out the effect. This may well change in iOS 7 since the visual appearance has changed.
[Edit]
This is a nice bit of debug code to inspect view hierarchies. (You can't call recursiveDescription
directly because it is private and your code won't compile under default Xcode settings.)
NSLog(@"%@", [self.view performSelector:@selector(recursiveDescription)]);
If you do the following it will fix your problem:
Get rid of the 'backingImage' (backingView). In stead use the cell's backgroundView
property, just assign the UIImageView
to that.
Now when you create your UIImageView
for the background make sure you make the UIImage
stretchable like this:
UIImage *bg = [UIImage imageName:@"filename.png"];
bg = [bg resizableImageWithCapInsets:UIEdgeInsetsMake(15, 0, 15, 0)];
NOTE: I'm assuming your image has a height of 30 points. Looking at the image you're using it can be stretched vertically, what I'm doing in this example. To save more memory you could also stretch it horizontally, but the asset you have may not lend itself for that.
Hope this helps!
On iOS 8 with no seperators on a grouped tableview I had the problem as well. There was a 0.5f point gap between my sections. Since the background behind my tableview was not the same color, it was very noticeable. The solution is to fill with a blank headerview 1 px high, then spill out of it by 1 px with another view. Works like a charm.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 1)];
view.backgroundColor = [UIColor whiteColor];
view.opaque = YES;
view.clipsToBounds = NO;
//Spill a view out by one pixel.
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 2)];
subView.backgroundColor = [UIColor whiteColor];
subView.opaque = YES;
[view addSubview:subView];
return view;
}
- (CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section {
return 1;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With