UITableViewCell 使用 separatorInset 隐藏分隔符在 iOS 11 中失败

SAH*_*AHM 5 uitableview ios ios11

这是我在 iOS 11 之前用于隐藏单个 UITableViewCell 的分隔符的代码:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (indexPath.row == 0) {


        // Remove separator inset
        if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
            [cell setSeparatorInset:UIEdgeInsetsMake(0, tableView.frame.size.width, 0, 0)];
        }

        // 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:UIEdgeInsetsMake(0, tableView.frame.size.width, 0, 0)];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,每个部分的第一行的分隔符都隐藏。我不想完全摆脱分隔符 - 仅适用于某些行。

在 iOS 11 中,上述代码不起作用。单元格的内容被完全推到右边。

有没有办法完成在 iOS 11 中隐藏单个 UITableViewCell 的分隔符的任务?

让我提前澄清一下,我确实知道我可以使用以下代码隐藏整个 UITableView 的分隔符(希望避免回答指示我这样做):

self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
Run Code Online (Sandbox Code Playgroud)

编辑:另外为了在下面的评论后澄清,如果我完全包含 setSeparatorInset 行,代码会做完全相同的事情。所以即使只有那一行,单元格的内容也会一直向右推。

Kam*_*ski 3

如果您不热衷于向您的应用程序添加自定义分隔符UITableViewCell我可以向您展示另一种需要考虑的解决方法。

怎么运行的

因为分隔符的颜色是在UITableView级别上定义的,所以没有明确的方法来更改它UITableViewCell实例更改它。这并不是苹果公司的初衷,你唯一能做的就是破解它。

您需要做的第一件事是访问分隔符视图。你可以用这个小扩展来做到这一点。

extension UITableViewCell {
    var separatorView: UIView? {
        return subviews .min { $0.frame.size.height < $1.frame.size.height }
    }
}
Run Code Online (Sandbox Code Playgroud)

当您有权访问分隔符视图时,您必须进行UITableView适当的配置。首先,将所有分隔符的全局颜色设置为.clear(但不要禁用它们!)

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.separatorColor = .clear
}
Run Code Online (Sandbox Code Playgroud)

接下来,设置每个单元格的分隔符颜色。您可以为每个人设置不同的颜色,具体取决于您。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "SeparatorCell", for: indexPath)
    cell.separatorView?.backgroundColor = .red

    return cell
}
Run Code Online (Sandbox Code Playgroud)

最后,对于该部分中的每个第一行,将分隔符颜色设置为.clear

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if indexPath.row == 0 {
        cell.separatorView?.backgroundColor = .clear
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么它有效

首先,让我们考虑一下 的结构UITableViewCell。如果打印出subviews单元格的内容,您将看到以下输出。

<UITableViewCellContentView: 0x7ff77e604f50; frame = (0 0; 328 43.6667); opaque = NO; gestureRecognizers = <NSArray: 0x608000058d50>; layer = <CALayer: 0x60400022a660>>
<_UITableViewCellSeparatorView: 0x7ff77e4010c0; frame = (15 43.5; 360 0.5); layer = <CALayer: 0x608000223740>>
<UIButton: 0x7ff77e403b80; frame = (0 0; 22 22); opaque = NO; layer = <CALayer: 0x608000222500>>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,有一个视图包含内容、分隔符和附件按钮。从这个角度来看,您只需要访问分隔符视图并修改其背景即可。不幸的是,这并不那么容易。

让我们看看UITableViewCell视图调试器中的相同内容。如您所见,有两个分隔符视图。您需要访问调用时不存在的底部一个willDisplay:。这就是第二个 hacky 部分发挥作用的地方。

表视图单元格的结构

当您检查这两个元素时,您将看到第一个(从顶部开始)的背景颜色设置为nil,第二个元素的背景颜色设置为您为整个 指定的值UITableView。在这种情况下,有颜色的分隔符覆盖没有颜色的分隔符。

要解决问题,就必须“扭转”局面。我们可以设置所有分隔符的颜色,以.clear显示我们有权访问的分隔符。最后,我们可以将可访问分隔符的背景颜色设置为所需的颜色。