【问题标题】:How do I eliminate the margin on the left side of a UITableView, without creating a gap on the right?如何消除 UITableView 左侧的边距,而不在右侧创建间隙?
【发布时间】:2015-03-12 08:04:28
【问题描述】:

我的目标是 iOS 7 和 8,我想消除下面这个 UITableView 中图像左侧出现的边距。如果解决方案简单/优雅,我什至愿意接受仅适用于 iOS 8 的解决方案。 (在 iOS 7 消亡时,我只能忍受它的余量)。

这是我想要的样子:

我已经阅读了许多关于 Stack Overflow (such as this one) 或特定于分组 UITableViews (herehere) 的类似问题,但似乎无法让任何问题正常工作。

例如,如果我尝试使用 contentInset(SO 上的常见答案)解决问题:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, -16, self.tableView.contentInset.bottom, self.tableView.contentInset.right);
    self.tableView.separatorInset = UIEdgeInsetsMake(0, 33, 0, 0);
}

然后我最终得到了tableview右侧的间隙:

我明白为什么会这样了,整个 tableview 只是移动了,如 Debug View Hierarchy 屏幕所示:

但是,我尝试调整 tableView 框架大小以进行补偿,但它似乎永远无法正常工作。另外,这看起来很老套;一定有更好的办法。

为了记录,这是我的 cellForRowAtIndexPath:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // get a cell that we can use]
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"VideoCell" forIndexPath:indexPath];

    cell.textLabel.numberOfLines = 0;

    cell.selectedBackgroundView = selectionColor;

    cell.accessoryView = [[UIImageView alloc] initWithImage:[PTStyleKit imageOfArrow]];

    // Create the attributed string (text + attributes)
    NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:[videos objectAtIndex:indexPath.row] attributes:attributes];

    // Set it in our UILabel and we are done!
    [cell.textLabel setAttributedText:attributedText];

    NSString* filename = [filenames objectAtIndex:indexPath.row];
    if (filename == nil)
    {
        filename = cell.textLabel.text;
    }

    UIImage *imageOne = [UIImage imageNamed:[NSString stringWithFormat:@"medium-%@", filename]];
    cell.imageView.image = [UIImage imageWithCGImage:imageOne.CGImage scale:imageOne.size.height/44 orientation:imageOne.imageOrientation];

    return cell;
}

【问题讨论】:

  • 看起来是 tableviewcell 的问题,而不是 tableview 本身的问题。您也可以发布您的cellForRowAtIndexPath: 方法吗?
  • 感谢您查看@Novarg,刚刚添加。
  • 你也可以调试那个方法并记录cell.imageView的位置吗?
  • @Novarg 我看到 x:0.000000, y: 0.000000 NSLog(@"x: %f, y: %f", cell.imageView.frame.origin.x, cell.imageView.frame.origin.y);。是这个意思吗?
  • 您总是可以使用 nib 制作自定义单元格,并且比使用默认 UITableviewCell 更容易且可自定义程度更高

标签: ios swift uitableview


【解决方案1】:

为表格视图设置清晰的背景并设置contentInset 属性。

代码:

tableView.contentInset = UIEdgeInsetsMake(0, -15, 0, 0);
tableView.backgroundColor = [UIColor clearColor];

但通过设置框架将表格视图的宽度增加 15 个像素。

【讨论】:

    【解决方案2】:

    看来我能找到的唯一解决方案是将 UITableViewCell 子类化,然后覆盖 imageView 和 textLabel 的布局。在研究这种方法时,我发现了this related answer。 (我想我一直没有意识到我一直在寻找最初在 iOS 6 中的 tableview 行为。)

    我的子类有这个唯一的重写方法:

    - (void)layoutSubviews
    {
        [super layoutSubviews];
    
        // Slide image to the left, eliminating gutter
        self.imageView.frame = CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height);
    
        // Slide text label to the left, and extend width by additional
        // space gained by eliminating the left-most gutter
        self.textLabel.frame = CGRectMake((self.imageView.frame.origin.x + self.imageView.frame.size.width + 15), 0, self.textLabel.frame.size.width + 15, self.textLabel.frame.size.height);
    }
    

    生成的表格视图现在看起来完全符合我的要求:

    【讨论】:

      【解决方案3】:

      1.在 iOS 13 上

      关键是和其他东西一起设置 cell.contentView.layoutMargins.zero

      /// view controller
      ...
      tableView.register(UITableViewCell.self, forCellReuseIdentifier: "identifier")
      tableView.separatorInset = .zero
      tableView.directionalLayoutMargins = .zero
      tableView.layoutMargins = .zero
      ...
      
      /// data source
      ...
      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      
          let cell = tableView.dequeueReusableCell(withIdentifier: "identifier")!
          cell.textLabel?.text = "Text"
          cell.directionalLayoutMargins = .zero
          cell.layoutMargins = .zero
          cell.contentView.directionalLayoutMargins = .zero
          cell.contentView.layoutMargins = .zero
          return cell
      }
      

      如果你正在使用 UITableViewController,除了以上所有你还需要应用这个:

      tableViewController.viewRespectsSystemMinimumLayoutMargins = false
      

      2。在 iOS 12 及更低版本上

      似乎没有办法使用 layoutMargins 等将标准 UITableViewCell.textLabel 放置到相对于表格的零偏移量。我发现的最简单也是唯一的方法是将单元格子类化并覆盖layoutSubviews,如下所示:

      class MyCell: UITableViewCell {
          ...
          override func layoutSubviews() {
              super.layoutSubviews()
              let leading = contentView.directionalLayoutMargins.leading
              textLabel?.frame.origin.x = leading
          }
          ...
      }
      

      当然,您需要正确设置布局边距才能正常工作

      【讨论】:

      • 该死的,这需要很多代码来简单地消除边距。虽然工作!谢谢
      • @AnatolyRudenko 您可以在底部的 Size Instpector 选项卡中设置 IB 中的 Layout Margins
      【解决方案4】:

      我想我刚刚想出了一个简单的解决方案,我在 stackoverflow 上找到了它,一种调整单元格边距的方法,在你的代码中添加这个方法

      -(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
          if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
              [tableView setSeparatorInset:UIEdgeInsetsZero];
          }
          if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
          [tableView setLayoutMargins:UIEdgeInsetsZero];
          }
          if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
          cell.preservesSuperviewLayoutMargins = NO;
          [cell setLayoutMargins:UIEdgeInsetsZero];
          }
          if ([cell respondsToSelector:@selector(setSeparatorInset:)]){
          [cell setSeparatorInset:UIEdgeInsetsZero];
          }
      }
      

      这解决了我的问题。

      Swift 3 和 4

      public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
          if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
              cell.separatorInset = .zero
          }
          if (cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins))) {
              cell.preservesSuperviewLayoutMargins = false
          }
      
          if (cell.responds(to: #selector(setter: UIView.layoutMargins))) {
              cell.layoutMargins = UIEdgeInsets.zero
          }
          if tableView.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
              tableView.separatorInset = .zero
          }
      
      }
      

      【讨论】:

        【解决方案5】:

        iOS 8+

        在您的表格视图中:

        table.separatorInset = UIEdgeInsets.zero     // or UIEdgeInsetsZero
        

        您可能还需要:

        table.layoutMargins = UIEdgeInsets.zero
        

        归功于https://stackoverflow.com/a/30640595/385273

        【讨论】:

          【解决方案6】:

          你可以试试;

          [cell.textLabel setTranslatesAutoresizingMaskIntoConstraints:false];
          [cell.textLabel.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor].active = YES;
          [cell.textLabel.leadingAnchor constraintEqualToAnchor:cell.contentView.leadingAnchor constant:22].active = YES; 
          

          【讨论】: