如何消除 UITableView 左侧的边距,而不在右侧创建间隙?

How do I eliminate the margin on the left side of a UITableView, without creating a gap on the right?

我的目标是 iOS 7 和 8,我想消除下面这个 UITableView 中图像左侧出现的边距。如果解决方案是 simple/elegant,我什至愿意接受仅适用于 iOS 8 的解决方案。 (我只接受 iOS 7 的边距,因为它消失了)。

这就是我想要的样子:

我在 Stack Overflow (such as this one), or ones specific to grouped UITableViews (here and here) 上通读了许多类似的问题,但似乎无法正确解决任何问题。

例如,如果我尝试使用 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 框架大小来补偿,但它似乎永远无法正常工作。另外这看起来很老套;一定有更好的方法。

作为记录,这是我的 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;
}

看来我能找到的唯一解决方案是子类化 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);
}

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

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

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

}

为您的 table 视图设置清晰的背景并设置 contentInset 属性。

代码:

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

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

iOS 8+

在您的 table 视图中:

table.separatorInset = UIEdgeInsets.zero     // or UIEdgeInsetsZero

您可能还需要:

table.layoutMargins = UIEdgeInsets.zero

归功于 。

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 相对于 table 的偏移量设为零。我找到的最简单也是唯一的方法是子类化单元格并像这样覆盖 layoutSubviews

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

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

你可以试试;

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