如何增加UITableView的分隔符高度?

57

我想在每个单元格之间增加10像素的间距。我该怎么做?

而我已经添加了这段代码

tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

1
如果在构建TableView的数据源时只有一个部分,您可以将N行更新为N个部分(每个部分只有一行),并使用部分标题作为分隔符。 - Itachi
请访问以下链接,您将以最佳方式获得解决方案...! https://dev59.com/IKLia4cB1Zd3GeqPpdZo#45893185 - Kiran Jadhav
17个回答

32

对我来说,最好的方法就是将这段代码添加到cellForRowAtIndexPath或willDisplayCell中。

CGRect sizeRect = [UIScreen mainScreen].applicationFrame;    
NSInteger separatorHeight = 3;
UIView * additionalSeparator = [[UIView alloc] initWithFrame:CGRectMake(0,cell.frame.size.height-separatorHeight,sizeRect.size.width,separatorHeight)];
additionalSeparator.backgroundColor = [UIColor grayColor];
[cell addSubview:additionalSeparator];

对于 Swift 3.0 版本:

let screenSize = UIScreen.main.bounds
let separatorHeight = CGFloat(3.0)
let additionalSeparator = UIView.init(frame: CGRect(x: 0, y: self.frame.size.height-separatorHeight, width: screenSize.width, height: separatorHeight))
additionalSeparator.backgroundColor = UIColor.gray
self.addSubview(additionalSeparator)

你应该将这个代码添加到单元格的awakeFromNib()方法中,以避免重新创建。


5
请检查是否已经添加了additionalSeparator,以免重复添加。由于单元格重用的原因,cellForRow...willDisplayCell可能会被多次调用,这会导致用户在滚动表格时性能下降。请注意优化。 - ikuramedia
@ikuramedia,我查看了项目。我在tableViewCell子类中的awakeFromNib方法中添加了额外的分隔符。当我滚动tableView时它没有被调用。不管怎样,我们应该小心谨慎,谢谢。 - Dmitry Soloviov
嗨 @ikuramedia。感谢您的反馈。但是,我的问题关于他最后的评论是,如果他也在cell的awakeFromNib中添加子视图分隔符,那么这是否会在tableview的cellForRowAtIndexPath方法之后调用,并且对于每个单元格都会调用.....因此它仍然会将子视图添加到重复使用的单元格中,并产生性能问题? - ScottEdwards2000
我认为awakeFromNib只会被调用于从storyboard原型创建的单元格,并且只应该在每个可重用单元格的初始创建时被调用,因此这听起来似乎是一个避免问题的好方法。只要它不会在cellForRow或willDisplayCell中也被创建就可以。 - ikuramedia
似乎这对于具有可变高度的单元格(例如,其中包含多行标签)无效,因为分隔符是在布局完成之前添加的。 - ndreisg

23

我见过很多笨拙的解决方案,比如用隐藏的单元格对UITableView进行子类化,以及其他不太理想的解决方法(本主题中也包含)。

在初始化UITableView时,将UITableViewrowHeight属性设置为一个高度,该高度等于单元格的高度 + 所需分隔符/空白区域的高度。

但不要使用标准的UITableViewCell类,而是对UITableViewCell类进行子类化,并重写其layoutSubviews方法。在那里,在调用super之后(不要忘记),将单元格本身的高度设置为所需高度。

BONUS UPDATE 18/OCT/2015:

你可以聪明一点。上面的解决方法基本上将“分隔符”放在了单元格底部。实际上,行高由TableViewController管理,但单元格被调整为更低的高度。这导致分隔符/空白间隔在底部。但是,你还可以垂直居中所有子视图,以便在顶部和底部留下相同的空间。例如1pt和1pt。

你还可以在单元格子类中创建isFirst、isLast的便利属性。在cellForRowAtIndexPath中将其设置为yes。这样,你就可以在layoutSubviews方法中处理顶部和底部分隔线的边缘情况,因为该方法可以访问到这些属性。 这样你可以处理顶部或底部的特殊情况 - 因为有时设计部门想要N+1个分隔符,而单元格的数量只有N个。因此,你必须以一种特殊的方式处理顶部或底部的分隔线。但最好是在单元格内部处理这些情况,而不是在tableViewHeader或TableViewFooter中处理。


1
嗨@EarlGrey。据我所知,自定义单元格的layoutSubviews在tableview调用heightForRowAtIndexPath和cellForRowAtIndexPath之后被调用。那么,在layoutSubviews中设置每个单元格的高度是否会重置它,无论它是新单元格还是重用单元格?如果是这样,对于动态tableview,如果您重置了重用单元格的高度,是否会导致性能问题?想要深入了解细节以增加自己的知识。感谢您的反馈。 - ScottEdwards2000

14

我认为使用标准 API 是不可能的。我猜你需要子类化 UITableViewCell 并添加一个视图,模拟一个在单元格底部的分隔符。

你可能想要查看这个问题,它看起来相关并且有一些示例代码: iPhone + UITableView + place an image for separator


7
Swift 中,对我来说最简单、最短的方法是将以下代码片段添加到 cellForRowAtIndexPathwillDisplayCell 中:
override func tableView(tableView: UITableView,
                        willDisplayCell cell: UITableViewCell,
                        forRowAtIndexPath indexPath: NSIndexPath)
{
        let additionalSeparatorThickness = CGFloat(3)
        let additionalSeparator = UIView(frame: CGRectMake(0,
                                                           cell.frame.size.height - additionalSeparatorThickness,
                                                           cell.frame.size.width,
                                                           additionalSeparatorThickness))
        additionalSeparator.backgroundColor = UIColor.redColor()
        cell.addSubview(additionalSeparator)
}

7
不要像上面那样添加单元格!对于每个“可重用”的单元格,您应当添加一个子视图。在添加之前为子视图打标签,并使用viewWithTag: TAG:获取标签。如果返回nil,则继续标记和添加。有关标签的信息,请参见此处示例:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TableView_iPhone/TableViewCells/TableViewCells.html - ingconti
将子视图添加到UITableViewCell的委托方法上从来都不是一个好主意。如果需要添加子视图,请对其进行子类化并在子类中添加。 - Cagdas Altinkaya
CGRectMake和UIColor.redColor()在Swift 3中不再支持。 - Dashrath
即使我们将语法更改为Swift 3.0,它也会在单元格内部添加红线而不是在其后面。是否有一种方法可以在单元格后面添加分隔符? - Dashrath

5
这篇文章有些老旧,但我仍会分享我的方法。
只需稍微增加单元格的高度,并为单元格分配一个遮罩层,就像这样:
```html

只需稍微增加单元格的高度,并为单元格分配一个遮罩层,就像这样:

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

    // Configure the cell...
    let maskLayer = CAShapeLayer()
    let bounds = cell.bounds
    maskLayer.path = UIBezierPath(roundedRect: CGRect(x: 2, y: 2, width: bounds.width-4, height: bounds.height-4), cornerRadius: 5).cgPath
    cell.layer.mask = maskLayer

    return cell
}

在这个例子中,我的分隔符高度将是4。
玩得开心!

编辑:这会导致行动作消失。 - Neil Sardesai

3

虽然这是一个有点老的帖子,但是在这个帖子中我只找到了一些hacky(指不规范的)解决方案,下面是对我最有效的解决方案的介绍(不需要在每个单元格中添加额外的UIView)。

Swift 3:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    //configure your cell...

    cell.layer.shadowColor = UIColor.red.cgColor
    cell.layer.shadowOffset = CGSize(width: 0, height: 1)
    cell.layer.shadowOpacity = 1
    cell.layer.shadowRadius = 0
    cell.layer.masksToBounds = false

    return cell
}

编辑:不幸的是,如果您在表格中向上滚动,这种方法就不起作用了。无论如何,我仍然在此处提供答案,因为它可能是您的表格有限内容的解决方案。

更多信息请查看“滚动时UITableViewCell上的阴影消失”


今天我注意到,当我在tableView中向上滚动时,这个解决方案不起作用 :( - ndreisg

3
您可以完全在Storyboard中完成此操作。以下是具体步骤:
  • 进入Storyboard并选择Table View
  • 显示Size Inspector,然后设置行高为140。
  • 然后显示Attributes Inspector,从中设置分隔符为Single Line,样式为Plain,并选择颜色。
  • 然后在Storyboard中(或文档大纲中)选择单元格
  • 再次在Size Inspector下的Table View Cell中设置自定义行高为120。
这就是全部操作了。您的分隔符将高20个单位。

13
不支持动态单元格,使用Swift + iOS 8.3 + Xcode版本6.3.2。 - King-Wizard

2

Swift 4

默认分隔符的高度无法更改。相反,您需要为每个单元格添加一个看起来像分隔符的子视图(并可选地使单元格更高)。例如,您可以在cellForRowAtIndexPathUITableViewCell子类中执行此操作。

如果允许选择单元格,则还需要添加所选状态的子视图,否则当选择单元格时分隔符将消失。这就是为什么还要配置selectedBackgroundView的原因。

将以下内容添加到您的UITableViewController子类中:

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.separatorStyle = .none
}

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

    cell.backgroundView = UIView(backgroundColor: .white)
    cell.backgroundView?.addSeparator()

    cell.selectedBackgroundView = UIView(backgroundColor: .blue)
    cell.selectedBackgroundView?.addSeparator()

    // configure the cell

    return cell
}

请将以下扩展程序添加到同一文件的底部:

private extension UIView {
    convenience init(backgroundColor: UIColor) {
        self.init()
        self.backgroundColor = backgroundColor
    }

    func addSeparator() {
        let separatorHeight: CGFloat = 2
        let frame = CGRect(x: 0, y: bounds.height - separatorHeight, width: bounds.width, height: separatorHeight)
        let separator = UIView(frame: frame)
        separator.backgroundColor = .gray
        separator.autoresizingMask = [.flexibleTopMargin, .flexibleWidth]

        addSubview(separator)
    }
}

2

对于高度为50且行间距为5像素的表格单元格。宽度为320。

将单元格的背景定义为透明:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColor = [UIColor clearColor];
}

设置单元格的高度,即行的大小加上分隔符的大小:

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 55;
}

在cellForRowAtIndexPath方法中定义一个框,大小为行高(减去分隔符),用背景颜色进行填充:
UILabel *headerBackgroundLabel = [[UILabel alloc] initWithFrame:CGRectMake(0,0,320,50)];
backgroundBox.backgroundColor = [UIColor grayColor];
[cell addSubview:backgroundBox];

2

我以更简单和灵活的方式完成。有些人可能称之为黑客行为,但我认为它很实用。

我隐藏了标准的UITableViewSeparator。然后,在单元格中添加一个子视图,使用自动布局将其固定在顶部。将其高度设为所需高度。两侧留有一定的边距并将其钉住到边缘。改变它的背景颜色。这样我就拥有了我想要的纯分隔符。

你可能会质疑在单元格层次结构中再加入另一个UIView的效率。它真的会有明显的区别吗?也许不会——毕竟,你已经将标准分隔符从表格层次结构中删除了。


1
和其他单元格一样。我也将表头用作顶部边距,所以这可能会有所不同。 - bandejapaisa
我做了同样的事情。我在XIB的顶部和底部添加了一个UIView,每个4像素,这样“分隔符”就会是8像素。 - Vidal Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接