协慌网

登录 贡献 社区

iOS 8 UITableView 分隔符插入 0 不起作用

我有一个应用程序,其中UITableView的分隔符插入设置为自定义值 - 右0 ,左0iOS 7.x可以完美运行,但是在iOS 8.0我看到分隔符插入设置为右侧15即使在 xib 文件中将其设置为0 ,它仍然显示不正确。

如何删除UITableViewCell分隔符边距?

答案

iOS 8.0 在单元格和表视图上引入了 layoutMargins 属性。

此属性在 iOS 7.0 上不可用,因此您需要确保在分配前检查一下!

最简单的解决方法是对单元格进行子类化,并覆盖 @ user3570727 所建议的 layout margins 属性。但是,您将失去任何系统行为,例如从安全区域继承边距,因此我不建议您使用以下解决方案:

(目标 C)

-(UIEdgeInsets)layoutMargins { 
     return UIEdgeInsetsZero // override any margins inc. safe area
}

(第 4.2 节):

override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }

如果您不想覆盖该属性,或者需要有条件地对其进行设置,请继续阅读。


除了layoutMargins属性外,Apple 还向您的单元格添加了一个属性,以防止其继承表视图的边距设置。设置此属性后,将允许您的单元格独立于表格视图配置其自己的边距。将其视为替代。

此属性称为preservesSuperviewLayoutMargins ,并将其设置为NO将允许单元格的layoutMargin设置覆盖在 TableView 上设置的所有layoutMargin这既节省时间(您不必修改表视图的设置),也更加简洁。请参阅 Mike Abdullah 的回答以获取详细说明。

注意:下面是 Mike Abdullah 的回答所表示的单元格级边距设置的干净实现。设置单元格的preservesSuperviewLayoutMargins=NO将确保您的表视图不会覆盖单元格设置。如果您实际上希望整个表格视图具有一致的页边距,请相应地调整代码。

设置您的单元格边距:

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Remove seperator inset
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
           [cell setSeparatorInset:UIEdgeInsetsZero];
    }

    // Prevent the cell from inheriting the Table View's margin settings
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        [cell setPreservesSuperviewLayoutMargins:NO];
    }

    // Explictly set your cell's layout margins
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

斯威夫特 4:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    // Remove seperator inset
    if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
        cell.separatorInset = .zero
    }
    // Prevent the cell from inheriting the Table View's margin settings
    if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
        cell.preservesSuperviewLayoutMargins = false
    }
    // Explictly set your cell's layout margins
    if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
        cell.layoutMargins = .zero
    }
}

将单元格上preservesSuperviewLayoutMargins属性设置为 NO 应该可以防止表格视图覆盖单元格边距。在某些情况下,它似乎无法正常运行。

如果全部失败,则可以强行使用 Table View 边距:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    // Force your tableview margins (this may be a bad idea)
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        [self.tableView setSeparatorInset:UIEdgeInsetsZero];
    }

    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        [self.tableView setLayoutMargins:UIEdgeInsetsZero];
    }
}

斯威夫特 4:

func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // Force your tableview margins (this may be a bad idea)
    if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
        tableView.separatorInset = .zero
    }
    if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
        tableView.layoutMargins = .zero
    }
}

... 然后您就去了!这应该可以在 iOS 7 和 8 上使用。


编辑: Mohamed Saleh 使我注意到了 iOS 9 中的可能更改。如果您要自定义插图或边距,则可能需要将表视图的cellLayoutMarginsFollowReadableWidthNO您的里程可能会有所不同,但记录不充分。

此属性仅在 iOS 9 中存在,因此请务必在设置前进行检查。

if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
    myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}

斯威夫特 4:

if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
    myTableView.cellLayoutMarginsFollowReadableWidth = false
}

(以上来自iOS 8 UITableView 分隔符 inset 0 的代码不起作用)

编辑:这是一个纯接口生成器方法:

TableViewAttributesInspector TableViewCellSizeInspector

注意:iOS 11 更改并简化了许多这种行为,即将发布更新...

啊! Cell子类中进行任一操作之后,请执行以下操作:

- (UIEdgeInsets)layoutMargins
{
    return UIEdgeInsetsZero;
}

或设置cell.layoutMargins = UIEdgeInsetsZero;为我修复它。

让我们花点时间来理解问题,然后再盲目尝试解决。

在调试器中快速浏览一下会发现分隔线是UITableViewCell子视图。似乎单元本身对这些线的布局负有相当大的责任。

iOS 8 引入了布局边距的概念。默认情况下,视图的8pt ,它们是从祖先视图继承而来的。

尽我们所知,在布局分隔线时, UITableViewCell选择尊重左侧布局边距,使用它来约束左侧插图。

将所有这些放在一起,以实现理想的真正零插入,我们需要:

  • 将左侧布局边距设置为0
  • 停止所有继承该值的边距

这样写,这是一个非常简单的任务:

cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;

注意事项:

  • 该代码仅需要在每个单元格中运行一次(毕竟,您只是在配置单元格的属性),并且选择执行它没有什么特别的地方。做对您来说最干净的事情。
  • 可悲的是没有财产可供在 Interface Builder 配置,但你可以指定一个用户自定义运行时属性preservesSuperviewLayoutMargins如果需要的话。
  • 显然,如果您的应用程序也针对较早的 OS 版本,则需要避免执行上述代码,直到在 iOS 8 及更高版本上运行。
  • 可以将祖先视图(例如表)配置为也具有0左边界,而不是设置preservesSuperviewLayoutMargins ,但是由于您不控制整个层次结构,这似乎更容易出错。
  • 0 ,其余设置为空白可能会更干净一些。
  • UITableView在普通样式表的底部绘制的 “额外” 分隔符上有一个 0 插入,我想这也需要在表级别指定相同的设置(尚未尝试过此设置!)