我有一个以编程方式创建的分组UITableview。我也有一个以编程方式在tableview中填充的xib文件的单元格。到现在为止还挺好。但是我只想删除外部分隔线。我使用下面的代码,但是这次删除了所有分隔线。
self.tableView.separatorColor = [UIColor clearColor];
对于我的情况,这不是一个好选择。这是我想做的截图。
我有一个以编程方式创建的分组UITableview。我也有一个以编程方式在tableview中填充的xib文件的单元格。到现在为止还挺好。但是我只想删除外部分隔线。我使用下面的代码,但是这次删除了所有分隔线。
self.tableView.separatorColor = [UIColor clearColor];
对于我的情况,这不是一个好选择。这是我想做的截图。
Plain tableview
,而不是分组。在“分组”中,将分隔符放在页眉和页脚上。
Answers:
我刚刚制定了一个解决方案,就像单元格中contentView
的一样UIView
,所以我认为您可以专注于的底线contentView
。
这是我的代码:
首先,您必须清除分隔符
tableView.separatorColor = UIColor.clear
二,在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)
在这里,您将看到如下界面:
即使在2018年,Google仍将此页面作为该问题的最高结果。使用提供的任何答案,我在iOS 11中都没有运气,所以这是我想到的:
extension UITableViewCell {
func removeSectionSeparators() {
for subview in subviews {
if subview != contentView && subview.frame.width == frame.width {
subview.removeFromSuperview()
}
}
}
}
现在,在任何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
}
感觉不那么优雅,但是我还没有遇到任何问题。
编辑:看起来我们也需要这个(对于重复使用的单元格):
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.removeSectionSeparators()
}
这是此代码的屏幕截图中的之前/之后:
检查视图层次结构之后,似乎每个UITableViewCell只有三个子视图:内容视图(UITableViewCellContentView
)和两个分隔符视图(_UITableViewCellSeparatorView
)。我不喜欢NSStrings中的动态类实例化(Apple😉也不喜欢)。然而,因为contentView
一个UITableViewCell
是不使用私有API的访问,该解决方案被证明是相当容易的。
这个想法只是要遍历的子视图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
}
}
}
}
tableView(:willDisplayCell:forRowAtIndexPath:)
在表格视图呈现期间多次调用,因此上文通过检查单元格具有多少个子视图来跟踪状态。如果它具有三个子视图,则两个分隔符均保持不变。它还仅删除一个分隔符,但是您可以通过删除来删除两个分隔符break
。您还可以通过检查子视图的框架来指定是删除顶部分隔符还是底部分隔符。如果框架的y轴原点为0
,则为顶部分隔符。如果不是0
,那是底部。
希望这可以帮助!
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()
}
}
NSStringFromClass
这些值"_UITableViewCellSeparatorView"
并"UITableViewCellContentView"
与比较,然后将其删除。
#available
对于任何大于当前版本的iOS版本,建议您将该属性与空主体一起使用。
用于删除每个部分的分隔线的顶部和底部。将此添加到您的静态单元格。
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()
}
}
}
结果如下图
这是一个确实很老的问题,它仍然是搜索如何删除每个部分的顶部和底部分隔符时在Google上的第一批条目之一。
经过一番调查,我发现,如果没有愚蠢的视图层次结构的骇客攻击,苹果公司将没有办法也没有意图使这种事情发生。
幸运的是,有一种绝对简单的方法可以实现这种外观:
我说的很简单,但是对于初学者来说,这可能很困难,因为缺乏对如何UITableView
工作以及如何实现自己的单元的了解。让我尝试解释一下:
UITableViewCell
子类@IBOutlet weak var separatorView: UIView!
属性UITableView
小号Separator Style
来None
隐藏默认的分隔符UIView
拖到您的单元格上并调整其大小,使其位于单元格的底部(或顶部)。使用Size Inspector
sAutoresizing
将其固定到开始/结束/底部,并为其提供弹性宽度(或“自动布局”,在这种情况下,就在顶部)UITableViewDataSource
s中,根据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
}
}
这里是一些屏幕截图:
是的,这是一项工作,但是编码时没有免费的方法。最后,我们是程序员,编写代码取决于我们。花5到10分钟的时间进行设置总比只复制粘贴一些骇人的代码更好,后者在将来苹果决定更改视图层次结构时可能无法继续工作。
编写此答案实际上比实现分隔符要花更多的工夫。我也一直在寻找一种简单快捷的解决方案,但最终没有一个值得我使用的好的解决方案。
我希望您也看到在循环运行时遍历单元格子视图以隐藏或什至在视图层次结构中从视图层次结构中删除视图时,也感到怀疑,这是苹果为您提供的简便,通用,稳定和面向未来的解决方案。只需要做7个小步骤,它们就很容易理解。
这是我最终想出的:
我找不到比这更好的方法了。但这对我很有帮助。上次尝试使用Xcode版本7.3.1(7D1014)。此过程通过情节提要进行。
基本上,我在UITableViewCell上添加了一个高度为0.5 pt的UIView,然后为该UIView设置了背景颜色。将父UITableView的Separator设置为None。
详细信息如下:
考虑到您已经设置了UITableViewCell,custom还是default。在第一阶段,将UITableView的分隔符设置为None。
接下来添加一个高度为1 pt的UIView并根据需要设置Background,在我的情况下为Red。
开始设置约束。问题是将UIView的高度设置为0.5磅。这是此工作流程的唯一问题问题。
共享设置UIView高度0.5磅的方法。
首先(1)固定视图,然后(2)将高度设置为0.5。按Enter键。
最后,您的UIView将类似于以下内容。
除了这种方式,我无法将高度设置为0.5。
这里解决。这是针对静态单元格的。如果要动态,则只需重写“ count”。希望能帮助到你。
extension NSObject {
var theClassName: String {
return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
}
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.separatorStyle = .None
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let count = tableView.numberOfRowsInSection(indexPath.section)
if ( indexPath.row != count - 1 ) {
for view in cell.subviews {
if view.theClassName == "_UITableViewCellSeparatorView" {
view.backgroundColor = UIColors.redColor()
}
}
}
}
根据库克的答案,但没有计时器:
override func didAddSubview(_ subview: UIView) {
super.didAddSubview(subview)
if NSStringFromClass(subview.classForCoder) != "UITableViewCellContentView" && subview.frame.width == frame.width {
subview.removeFromSuperview()
}
}
只需将其添加到单元的子类中,就不需要其他任何东西了。适用于iOS 12。
iOS 13,迅捷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
}
}
我要感谢@cook提供的此解决方案,因为它是基于它的。我的解决方案有一些问题:
layoutSubviews()
,还没有一个问题。==
,这听起来容易出错。我在代码中添加了“选项#2”,因为这是我亲自寻找的解决方案(我想维护分隔符,但我希望它与常规单元格分隔符具有相同的缩进级别,在我的情况下,值16)。
我有一个类似的问题,我有一个带有自定义单元格的分组UITableView,所有这些都使用Interface Build设计为.xib文件。单元格具有白色背景,删除了默认的分隔符,并添加了我自己的分隔符。我还为每个部分定制了标题视图。我将这些“标题视图”的高度设置为44(可以是任何...)。我的部分之间有一个1点高度的视图,这看起来很奇怪。显然,即使我们将自定义高度指定为44,并且返回的自定义页眉视图具有白色(或某些具体的背景颜色),系统也会在各节之间添加一些清晰的背景视图。我们在透明视图后面看到的颜色实际上是表格视图背景的颜色。就我而言,表格视图和单元格都必须为白色,并将表格视图的背景设置为白色可以解决此问题(至少在视觉上是这样,但这还是我想要的)。第二种解决方案是保持Table View的样式简单,但是实现UITableView委托方法以返回2个或更多部分,并在需要时创建自定义标头。但这会使标题视图在滚动时一直停留在顶部一段时间(直到滚动),直到下一节的标题视图离它更近,然后它也开始上升(这可能不是您真正想要的,但是在那里可能是解决此问题的简便方法,但不确定)。
您可以使用以下方式访问视图
override func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header = view as! UITableViewHeaderFooterView
header.backgroundView . .....
尝试此操作将删除顶部分隔线。
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 0 && indexPath.section == 0) {
for (UIView *view in cell.subviews) {
if ([NSStringFromClass([view class]) containsString:@"CellSeparator"]) {
if (view.frame.origin.y == 0 && CGRectGetHeight(view.frame) < 1.01 ) { //Hide first UITableViewCellSeparatorView
NSLog(@"%s Remove View From Cell[Section:0 Row:0] for top border [%@]:%@",__FUNCTION__,NSStringFromClass([view class]),view);
view.hidden = YES; //Hide
}
}
}
}
}
对于单单元格部分,只需覆盖layoutSubviews
并将其保留为空就可以了!https://stackoverflow.com/a/59733571/4442627
iOS 10〜13只能删除节头脚线。
-(void)layoutSubviews{
[super layoutSubviews];
//for iOS10~iOS13: only remove section head foot line
for (UIView * v in self.subviews) {
if ( v != self.contentView &&
(v.frame.size.width == self.frame.size.width)){
[v removeFromSuperview];
}
}
}
如果要删除所有行:
for (UIView * v in self.subviews) {
if (v != self.contentView){
[v removeFromSuperview];
}
}
override func layoutSubviews() {
super.layoutSubviews()
subviews.filter { $0 != contentView && $0.frame.width == frame.width }.first?.removeFromSuperview()
}
这是一个可在iOS 8和9上运行的Swift解决方案。
使用默认实现定义协议:
protocol CellSeparatorRemovable { }
extension CellSeparatorRemovable {
func removeSeparatorLinesFromCell(cell: UITableViewCell, section: Int, row: Int, indexPath: NSIndexPath) {
guard (section, row) == (indexPath.section, indexPath.row) else { return }
for view in cell.subviews where view != cell.contentView {
view.removeFromSuperview()
}
}
}
然后,无论您要在哪里使用它,都必须遵守CellSeparatorRemovable
协议并从中调用其方法…willDisplayCell…
:
class SomeVC: UITableViewController, CellSeparatorRemovable {
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
removeSeparatorLinesFromCell(cell, section: 1, row: 1, indexPath: indexPath)
}
}
这是一个最小的解决方案。如果要处理许多单元,则可能需要对其进行重构,以避免过多的递归和/或单元重用问题。
UIView
s作为伪分隔符添加到单元格中。希望有更好的选择。