分组 UITableView 中第一个和第二个单元格之间的 1 个像素间隙

Posted

技术标签:

【中文标题】分组 UITableView 中第一个和第二个单元格之间的 1 个像素间隙【英文标题】:1 pixel gap between first and second cell in grouped UITableView 【发布时间】:2013-01-31 23:28:27 【问题描述】:

这似乎是一个简单的问题,但我在寻找解决方案时遇到了困难,我希望这里有人可以提供帮助...

我正在使用 UITableViewStyleGrouped 制作 UITableView,我在表格视图的每个部分的第一行和第二行之间看到一条小的(1 像素)白线(见图)

这条线的原因似乎是每个部分的第一个单元格比其他单元格高 1 个像素。当我将每组的初始单元格设置为 29 像素高(其他为 30 像素)时,间隙消失了,一切都很好。

虽然这是一种成功的解决方法,但我宁愿知道发生这种情况的原因,这样我就可以避免使用凌乱的 hack。

仅供参考:

我已确保这不是我使用的背景图片的问题 - 它们都是 30 像素高,我已将顶部图片替换为具有相同结果的中间图片。 我通过设置 separatorStyle = UITableViewCellSeparatorStyleNone 删除了单元格之间的所有边框 UITableViewStylePlain 上不会出现这种效果

非常感谢任何帮助。

谢谢

表格设置代码:

  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;

单元设置代码:

- (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;

MyTableViewCell 中设置背景图片的代码:

- (void)setBackingImage:(UIImage *)backingImage

  if (self.backingImage != backingImage)
  
    _backingImage = nil;
    _backingImage = backingImage;
    self.backingView.image = backingImage;
  

self.backingView 使用以下代码设置:

[[UIImageView alloc] initWithFrame:CGRectMake(7, 0, 307, 30)];

【问题讨论】:

我们能看到一些代码吗?你在 heightForRowAtIndexPath: 中有什么事情吗? 单元格视图相关的代码会很好。您要向单元格中的哪个视图添加视图,单元格本身,contentView 还是 backgroundView?您添加自己的带有边框的图像?我做了一些测试,我认为分隔符样式不适用于分组表,它们总是绘制分隔符。 我已经添加了所有我能想到的可能会影响表结构的代码。如果需要,我很乐意添加任何其他内容... PS。 heightForRowAtIndexPath: 中的破解是我目前的解决方法。如果黑客被删除,差距会重新出现 只有添加背景图片才会出现while行吗?如果您没有单元格的任何背景图像怎么办?既然图像中没有不规则的图案,为什么不将单元格的颜色设置为 [UIColor colorWithPattern:backingImage]; ? (我也很想知道为什么会出现白线) 在这种情况下,边框包含在图像中,因此带图案的图像会产生不需要的效果。降低单元格高度的技巧似乎是一个合理的解决方法,但在分组表视图中,第一个单元格高 1 个像素似乎很奇怪(我想知道为什么)。这与使用的图像无关 - 图像只是突出显示效果 【参考方案1】:

这是一个已知问题,仅在您隐藏分组 tableView 的分隔符时发生,在另一个 stack overflow question 中发生完全相同的事情。

简单来说,上下单元格使用了一个额外的point,但是分隔符隐藏了它,所以解决方法是:

    减去额外的间距(就像你已经做过的那样) 使背景成为重复图案或可拉伸图像(不是想推销自己,但上一个链接线程上的the answer I gave 也解释了如何制作可拉伸图像)。 不要隐藏分隔符,而是将颜色与单元格的背景相匹配,使其看起来像是隐藏的。

选项 2 似乎是“最干净的”,并增加了支持 tableView 单元格可变高度的好处。

为什么它有额外的?只有苹果知道。

【讨论】:

三个好的解决方案,其中 #1 最符合我的要求。我宁愿让所有行都具有相同的高度,而不是拉伸我的背景以适应那个额外的点。在这里还值得注意的是,我没有看到底行表现出相同的行为 - 该行似乎总是 30 分,就像其余的一样。不得不诉诸这种肮脏的方法是一种耻辱,但正如你所说 - 苹果只知道它为什么会这样......【参考方案2】:

根据我的经验,分组表视图在每个部分的第一行和最后一行的高度上增加 1 个点(不是像素!)。您应该能够通过添加调试代码来覆盖表格单元格类上的 layoutSubviews 来看到这一点,让它调用 super 然后打印 bounds.size.height。

我认为这是为边框绘制提供空间,并且像您一样,我刚刚调整了返回的第一个和最后一个单元格的高度值以抵消效果。这在 ios 7 中很可能会发生变化,因为视觉外观发生了变化。

[编辑] 这是一个很好的调试代码来检查视图层次结构。 (您不能直接调用recursiveDescription,因为它是私有的,并且您的代码不会在默认的 Xcode 设置下编译。)

NSLog(@"%@", [self.view performSelector:@selector(recursiveDescription)]);

【讨论】:

请您澄清一下您提到的点和像素之间的区别?你的意思是一个点是通用表示并在视网膜显示器上显示为 2 个像素? 是的,这正是我的意思。您通过查看您的视网膜显示器来测量像素。要调整额外的间距,您需要使用 tableView:heightForRowAtIndexPath: 但将调整提供为点,而不是像素。【参考方案3】:

如果您执行以下操作,它将解决您的问题: 摆脱'backingImage'(backingView)。而是使用单元格的 backgroundView 属性,只需将 UIImageView 分配给它。 现在,当您为背景创建 UIImageView 时,请确保您使 UIImage 像这样可拉伸:

UIImage *bg = [UIImage imageName:@"filename.png"];
bg = [bg resizableImageWithCapInsets:UIEdgeInsetsMake(15, 0, 15, 0)];

注意:我假设您的图片高度为 30 磅。 查看您正在使用的图像可以垂直拉伸,我在这个例子中正在做的事情。为了节省更多内存,您还可以水平拉伸它,但您拥有的资产可能不适合这样做。

希望这会有所帮助!

【讨论】:

这是一个很好的答案,但不幸的是不是我想要的。虽然这将弥补差距,但我仍然留下第一行比其他行大 1 点...【参考方案4】:

在分组表视图上没有分隔符的 iOS 8 上,我也遇到了问题。我的部分之间有 0.5f 点的差距。由于我的 tableview 后面的背景不是相同的颜色,所以非常明显。解决方案是用 1 px 高的空白 headerview 填充,然后用另一个视图溢出 1 px。像魅力一样工作。

- (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;

【讨论】:

【参考方案5】:

这对我来说是尖叫的部分标题。您是否覆盖 viewForHeaderInSection 方法?我最好的猜测是,每个部分中第一个单元格的边界以某种方式与该部分标题的边界相重叠。

尝试覆盖这些方法:

– tableView:viewForHeaderInSection:
– tableView:viewForFooterInSection:
– tableView:heightForHeaderInSection:
– tableView:heightForFooterInSection:
– tableView:willDisplayHeaderView:forSection:
– tableView:willDisplayFooterView:forSection:

然后玩他们返回的东西。特别是 heightForHeaderInSection / viewForHeaderInSection / willDisplayHeaderView:ForSection:

【讨论】:

我尝试过覆盖这些方法,但这似乎没有任何效果。从上面 Can 和 Geoff 的回答来看,这似乎是一个已知问题,而不是由于这些委托方法的返回......

以上是关于分组 UITableView 中第一个和第二个单元格之间的 1 个像素间隙的主要内容,如果未能解决你的问题,请参考以下文章

在第二个和第三个连字符之间提取 TextString

Self Sizing Cells 使 UITableView 跳跃

SQL Regex 在第二个和第三个正斜杠之间选择字符串

插入排序

Self Sizing Cells使UITableView跳跃

分组UITableView,多个部分在iPhone SDK中创建问题