分组的UITableview删除外部分隔线

ser*_*zer 67 objective-c cell uitableview tableviewcell ios

我有一个分组的UITableview,它是以编程方式创建的.此外,我还有一个以编程方式填充tableview的xib文件的单元格.到现在为止还挺好.但我想只删除外部分隔线.我使用下面的代码,但这次删除了所有分隔线.

self.tableView.separatorColor = [UIColor clearColor];

这对我的情况来说不是一个好选择.这是我想要做的截图;

在此输入图像描述

Bro*_*ook 17

这是我的解决方案:

self.tableView.separatorColor = self.tableView.backgroundColor
Run Code Online (Sandbox Code Playgroud)

@xxtesaxx,你应该有一个真正的考验

  • 它会删除所有分隔符 (6认同)
  • @Brook它将删除所有分隔符.如果您阅读我的问题,我说我只想删除"外部"线. (3认同)
  • @serhatsezer 是的,我读了您的问题,这是一个技巧解决方案,它使外线“消失”并保持分隔线可见。 (3认同)
  • @Brook但是如果 tableView 背景颜色与分隔符颜色不同或 TableView 背景颜色与单元格颜色相同,就会出现问题。假设是白色。 (2认同)

mor*_*ter 13

即使在使用静态单元格的分组UITableView中,您也可以删除分隔符:

class CustomCell: UITableViewCell {

override func layoutSubviews() {
    super.layoutSubviews()
    for view in subviews where view != contentView {
        view.removeFromSuperview()
    }
}
Run Code Online (Sandbox Code Playgroud)


tit*_*tan 13

用于删除每个部分的分隔线的顶部和底部。将此添加到您的静态单元格。

override func layoutSubviews() {
    super.layoutSubviews()

    //Get the width of tableview
    let width = subviews[0].frame.width

    for view in subviews where view != contentView {
        //for top and bottom separator will be same width with the tableview width
        //so we check at here and remove accordingly
        if view.frame.width == width {
            view.removeFromSuperview()
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

结果如下图

在此处输入图片说明


coo*_*ook 10

即使是在2018年,Google也会将此页面作为此问题的最佳结果.我在iOS 11中没有任何提供任何答案的运气,所以这就是我想出的:

extension UITableViewCell {
    func removeSectionSeparators() {
        for subview in subviews {
            if subview != contentView && subview.frame.width == frame.width {
                subview.removeFromSuperview()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在任何UITableViewCell实例上调用.removeSectionSeparators()现在将解决问题.在我的情况下,至少,节分隔符是唯一与单元格本身具有相同宽度的分隔符(因为其他分隔符都是缩进的).

剩下的唯一问题是我们应该把它叫做什么.您认为willDisplayCell将是最佳选择,但我发现初始调用发生在生成分隔符视图之前,因此没有骰子.

在我返回重新加载的单元格之前,我最终把它放在我的cellForRowAtIndexPath方法中:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyReusableIdentifier", for: indexPath)

    Timer.scheduledTimer(withTimeInterval: 0.15, repeats: false) { (timer) in
        cell.removeSectionSeparators()
    }

    return cell
}
Run Code Online (Sandbox Code Playgroud)

它并不觉得优雅,但我还没有遇到任何问题.

编辑:看起来我们也需要这个(对于重用的单元格):

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    cell.removeSectionSeparators()
}
Run Code Online (Sandbox Code Playgroud)

这是使用此代码的截图中的前/后:

之前 拆除分隔符之前

拆除分隔符后

  • 就像魅力一样,谢谢。如果您在自定义类的布局子视图中调用它,效果会更好 (2认同)
  • 这是我能找到的唯一适用于 iOS 11 及以上版本的东西。谢谢。 (2认同)
  • 我尝试将此调用放入“willDisplay”或“cellForRowAt”中,但在我这边都不起作用。我正在使用 iOS 14 和 Swift5。 (2认同)

Dan*_*erz 9

在检查视图层次结构后,似乎每个UITableViewCell只有三个子视图:内容视图(UITableViewCellContentView)和两个分隔符视图(_UITableViewCellSeparatorView).我不是NSStrings动态类实例化的粉丝(也不是Apple).但是,由于可以在不使用私有API的情况下访问contentViewa UITableViewCell,因此解决方案非常简单.

这个想法只是遍历你的子视图UITableViewCell,并删除任何不是的视图contentView:

func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    let subviews = cell.subviews
    if subviews.count >= 3 {
        for subview in subviews {
            if subview != cell.contentView {
                subview.removeFromSuperview()
                break
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

tableView(:willDisplayCell:forRowAtIndexPath:)在表视图呈现期间多次调用,因此上面通过检查单元格具有多少个子视图来跟踪状态.如果它有三个子视图,则两个分隔符仍然完好无损.它也只删除其中一个分隔符,但你可以通过删除它们来删除它们break.您还可以通过检查子视图的框架来指定是删除顶部分隔符还是底部分隔符.如果框架的y轴原点是0,那就是顶部分隔符.如果不是0,那就是底部.

希望这可以帮助!

Swift 4,Swift 4.2更新:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let subviews = cell.subviews
    guard subviews.count >= 3 else {
        return
    }

    for subview in subviews where NSStringFromClass(subview.classForCoder) == "_UITableViewCellSeparatorView" {
        subview.removeFromSuperview()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 除非Apple更改tableviews的内部结构以具有多个内容视图,否则很可能不会.如果你想要更加小心,你可以使用`NSStringFromClass`并将这些值与`"_UITableViewCellSeparatorView"和`"UITableViewCellContentView"`进行比较,然后删除. (2认同)
  • Apple确实将tableViewCell视图层次结构从iOS 7更改为iOS 8,这确实使我在项目上非常恼火,因为我使用了这样的代码,所以我建议不要那样做。 (2认同)

小智 9

我刚刚制定了一个解决方案,就像该单元格contentView的一样UIView,所以我认为您可以专注于的底线contentView

这是我的代码:

首先,您必须清除分隔符

tableView.separatorColor = UIColor.clear
Run Code Online (Sandbox Code Playgroud)

二,在cellForRowAt功能上:

let bottomBorder = CALayer()

bottomBorder.frame = CGRect(x: 0.0, y: 43.0, width: cell.contentView.frame.size.width, height: 1.0)
bottomBorder.backgroundColor = UIColor(white: 0.8, alpha: 1.0).cgColor
cell.contentView.layer.addSublayer(bottomBorder)
Run Code Online (Sandbox Code Playgroud)

在这里,您将看到如下界面:

在此处输入图片说明


xxt*_*axx 7

这是一个非常古老的问题,在搜索如何删除每个部分的顶部和底部分隔符时,它仍然是 google 上的第一个条目。

经过一番调查,我发现 Apple 没有办法也没有意图让这种情况发生,而无需对视图层次结构进行愚蠢的复杂黑客攻击。

幸运的是,有一种绝对简单易行的方法可以实现这样的外观:

在此处输入图片说明

我说的很简单,但对于初学者来说,这可能很困难,因为缺乏了解如何UITableView工作以及如何实现自己的单元格。让我试着解释一下:

  1. 创建UITableViewCell子类
  2. 在您的单元格中,创建一个@IBOutlet weak var separatorView: UIView!属性
  3. 在您的 Storyboard 中,选择 tableview 单元格并选择您自己的单元格作为备份单元格的类。注意:您不必使用自定义样式。您仍然可以使用 Basic、Subtitle 等。
  4. 将您的UITableViewsSeparator Style设置None为隐藏默认分隔符
  5. 将 aUIView拖到您的单元格上并调整其大小,使其位于单元格的底部(或顶部)。使用Size InspectorsAutoresizing将它固定到开始/结束/底部并给它一个 flex 宽度(或自动布局,但在这种情况下只是在顶部)
  6. 将视图连接到单元类的出口
  7. 在您的UITableViewDataSources 中,根据是否是该部分的最后一行(或第一行,如果您的视图位于顶部)来cellForRowAtIndexPath:设置isHidden自定义分隔符的属性indexPath.row

下面是一些示例代码:

class MyCell: UITableViewCell {
    @IBOutlet weak var separatorView: UIView!
}

class ViewController: UITableViewController {


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MyCell
        cell.separatorView.isHidden = indexPath.row == 2
        return cell
    }

}
Run Code Online (Sandbox Code Playgroud)

这里有一些截图:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

是的,这是一些工作,但在编码时没有办法免费获得一些东西。最后,我们是程序员,由我们来进行编码。花 5 到 10 分钟的时间进行设置总是比复制粘贴一些在 Apple 决定更改视图层次结构时可能不会继续工作的黑客代码更好。

写这个答案实际上比实现分隔符要多得多。我也一直在寻找一种简单快捷的解决方案,但最终没有一个足够好的我觉得值得使用的解决方案。

我希望当您看到 for 循环迭代单元格的子视图以在运行时从视图层次结构中隐藏甚至删除视图时,您也会持怀疑态度 Apple 为您提供,当有一个简单、多功能、稳定且面向未来的解决方案就在眼前时. 7个小步骤真的是你所需要的,它们很容易理解。


Rai*_*idi 5

iOS 14,斯威夫特 5

在自定义单元格类中:

override func layoutSubviews(){
    super.layoutSubviews()
    
    for subview in subviews where (subview != contentView && abs(subview.frame.width - frame.width) <= 0.1 && subview.frame.height < 2) {
        subview.removeFromSuperview()                           //option #1 -- remove the line completely
        //subview.frame = subview.frame.insetBy(dx: 16, dy: 0)  //option #2 -- modify the length
    }
}
Run Code Online (Sandbox Code Playgroud)

我要感谢 @cook 提供的这个解决方案,因为我是在它之上构建的。我对他们的解决方案有一些问题:

  1. 它正在删除默认的突出显示/选定的背景视图,所以我添加了对子视图高度的额外检查。
  2. 我把我的代码放进去layoutSubviews()并没有遇到任何问题。
  3. 我在两个 CGFloats 之间实现了一个近似值,而不是使用相等运算符==,这对我来说听起来容易出错。

我在代码中添加了“选项 #2”,因为这是我个人正在寻找的解决方案(我想保留分隔符,但我希望它与常规单元格分隔符的缩进级别相同,在我的情况下为值 16)。