ios 分组 UITableview 删除外部分隔线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29006311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Grouped UITableview remove outer separator line
提问by serhat sezer
I have a grouped UITableview which is created programatically. Also I have a cell with xib file populated in tableview programmatically as well. So far so good. But I want to only remove outer separator line. I used below code but this time removed all separator line.
我有一个以编程方式创建的分组 UITableview。此外,我还有一个单元格,其中也以编程方式在 tableview 中填充了 xib 文件。到现在为止还挺好。但我只想删除外部分隔线。我使用了下面的代码,但这次删除了所有分隔线。
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.separatorColor = [UIColor clearColor];
this is not good option for my situation. Here is the screenshot what i want to do;
这对我的情况来说不是一个好选择。这是我想要做的截图;
采纳答案by Qi Lee
I just worked out a solution, as the cell has contentView
which is a UIView
, so I think you can just focus on the bottomline of contentView
.
我刚刚想出了一个解决方案,因为单元格有contentView
一个UIView
,所以我认为你可以只关注contentView
.
Here is my code:
这是我的代码:
first, you have to make the separator to clear
首先,您必须使分隔符清除
tableView.separatorColor = UIColor.clear
Second, in the cellForRowAt
function:
二、在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)
here you will see the UI like this:
在这里你会看到这样的用户界面:
回答by morizotter
You can remove separators even in grouped UITableView with Static Cell:
即使在带有静态单元格的分组 UITableView 中,您也可以删除分隔符:
class CustomCell: UITableViewCell {
override func layoutSubviews() {
super.layoutSubviews()
for view in subviews where view != contentView {
view.removeFromSuperview()
}
}
回答by Brook
回答by cook
Google, even in 2018, is serving this page as the top result for this question. I didn't have any luck in iOS 11 with any of the provided answers, so here's what I came up with:
即使在 2018 年,Google 也将此页面作为此问题的最佳结果。我在 iOS 11 中没有任何提供的答案的运气,所以这是我想出的:
extension UITableViewCell {
func removeSectionSeparators() {
for subview in subviews {
if subview != contentView && subview.frame.width == frame.width {
subview.removeFromSuperview()
}
}
}
}
Calling .removeSectionSeparators() on any UITableViewCell instance will now take care of the problem. In my case at least, the section separators are the only ones with the same width as the cell itself (as the other ones are all indented).
在任何 UITableViewCell 实例上调用 .removeSectionSeparators() 现在可以解决这个问题。至少在我的情况下,节分隔符是唯一与单元格本身宽度相同的分隔符(因为其他分隔符都缩进了)。
The only question left is from where we should call it. You'd think willDisplayCell would be the best choice, but I discovered that the initial call occurs before the separator views themselves are generated, so no dice.
剩下的唯一问题是我们应该从哪里称呼它。你会认为 willDisplayCell 是最好的选择,但我发现初始调用发生在分隔符视图本身生成之前,所以没有骰子。
I ended up putting this in my cellForRowAtIndexPath method just before I return a reloaded cell:
在返回重新加载的单元格之前,我最终将其放入我的 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
}
It doesn't feel that elegant, but I haven't run into any issues yet.
感觉不是那么优雅,但我还没有遇到任何问题。
EDIT:Looks like we need this too (for reused cells):
编辑:看起来我们也需要这个(对于重复使用的单元格):
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cell.removeSectionSeparators()
}
Here's a before/after in screenshots with this code:
这是带有此代码的屏幕截图的之前/之后:
回答by Dan Loewenherz
After inspecting the view hierarchy, it seems each UITableViewCell has only three subviews: the content view (UITableViewCellContentView
), and two separator views (_UITableViewCellSeparatorView
). I'm not a fan of dynamic class instantiation from NSStrings (and neither is Apple ). However, because the contentView
of a UITableViewCell
is accessible without using private APIs, the solution turns out to be pretty easy.
检查视图层次结构后,似乎每个 UITableViewCell 只有三个子视图:内容视图 ( UITableViewCellContentView
) 和两个分隔符视图 ( _UITableViewCellSeparatorView
)。我不喜欢 NSStrings 的动态类实例化(Apple 也不喜欢)。然而,因为contentView
aUITableViewCell
的 可以在不使用私有 API 的情况下访问,所以解决方案非常简单。
The idea is just to iterate through the subviews of your UITableViewCell
, and remove any views that aren't the contentView
:
这个想法只是遍历您的 的子视图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:)
is called multiple times during table view rendering, so the above keeps track of state by checking how many subviews the cell has. If it has three subviews, both separators are still intact. It also only removes one of the separators, but you can remove both by removing the break
. You can also specify whether to remove the top separator or the bottom separator by checking the subview's frame. If the frame's y-axis origin is 0
, that's the top separator. If it's not 0
, it's the bottom.
tableView(:willDisplayCell:forRowAtIndexPath:)
在表格视图渲染期间多次调用,因此上面通过检查单元格有多少子视图来跟踪状态。如果它有三个子视图,两个分隔符仍然完好无损。它也只删除一个分隔符,但您可以通过删除break
. 您还可以通过检查子视图的框架来指定是删除顶部分隔符还是底部分隔符。如果框架的 y 轴原点是0
,那就是顶部分隔符。如果不是0
,那就是底部。
Hope this helps!
希望这可以帮助!
Swift 4, Swift 4.2 Update:
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()
}
}
回答by xxtesaxx
That is a really old question, still it's one of the first entries on google when searching for how to remove the top and bottom separators for each section.
这是一个非常古老的问题,在搜索如何删除每个部分的顶部和底部分隔符时,它仍然是 google 上的第一个条目。
After some investigation, I found out that there is no way and just no intention from Apple to make this somehow happen without stupidly complicated hacks of the view hierarchy.
经过一番调查,我发现 Apple 没有办法也没有意图让这种情况发生,而无需对视图层次结构进行愚蠢的复杂黑客攻击。
Fortunately there is a absolutely simple and easy way of achieving such a look:
幸运的是,有一种绝对简单易行的方法可以实现这样的外观:
I say simple but for a beginner, this might be difficult because of a lack of understanding how UITableView
works and how to implement your own cells. Let me try to explain it:
我说的很简单,但对于初学者来说,这可能很困难,因为缺乏了解如何UITableView
工作以及如何实现自己的单元格。让我试着解释一下:
- Create a
UITableViewCell
subclass - In your cell, create a
@IBOutlet weak var separatorView: UIView!
property - In your Storyboard, select the tableview cell and select your own cell as the class which backs up the cell. Note: You do nothave to use custom style. You still can use Basic, Subtitle, etc.
- Set your
UITableView
sSeparator Style
toNone
to hide the default separator - Drag a
UIView
onto your cell and resize it so it is on the bottom (or the top) of the cell. Use theSize Inspector
sAutoresizing
to pin it to start/end/bottom and give it a flex width (or Autolayout but thats just over the top in this case) - Connect the view to the outlet of your cell class
- In your
UITableViewDataSource
scellForRowAtIndexPath:
set theisHidden
property of your custom separator based on if theindexPath.row
is the last row (or the first, if your view is at the top) in the section
- 创建
UITableViewCell
子类 - 在您的单元格中,创建一个
@IBOutlet weak var separatorView: UIView!
属性 - 在您的 Storyboard 中,选择 tableview 单元格并选择您自己的单元格作为备份单元格的类。注意:您不必使用自定义样式。您仍然可以使用 Basic、Subtitle 等。
- 将您的
UITableView
sSeparator Style
设置None
为隐藏默认分隔符 - 将 a
UIView
拖到您的单元格上并调整其大小,使其位于单元格的底部(或顶部)。使用Size Inspector
sAutoresizing
将它固定到开始/结束/底部并给它一个 flex 宽度(或自动布局,但在这种情况下只是在顶部) - 将视图连接到单元类的出口
- 在您的
UITableViewDataSource
s 中,根据是否是该部分的最后一行(或第一行,如果您的视图位于顶部)来cellForRowAtIndexPath:
设置isHidden
自定义分隔符的属性indexPath.row
Heres some example code:
下面是一些示例代码:
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
}
}
And here some screenshots:
这里有一些截图:
Yes, it is some work but there is just no way to something for free when coding. In the end, we are programmers and it is up to us to do the coding. It's always better to spend the 5-10 minutes setting this up than just copy pasting some hacky code which might not continue to work in the future when Apple decides to change the view hierarchy.
是的,这是一些工作,但在编码时没有办法免费获得一些东西。最后,我们是程序员,由我们来进行编码。花 5 到 10 分钟的时间进行设置总是比复制粘贴一些在 Apple 决定更改视图层次结构时可能不会继续工作的黑客代码更好。
It was actually more work to write this answer than implementing the separator. I as well was searching for a easy and quick solution but in the end there just wasn't a good enough one which I felt was worth using.
写这个答案实际上比实现分隔符要多得多。我也一直在寻找一种简单快捷的解决方案,但最终没有一个足够好的我觉得值得使用的解决方案。
I hope you also feel skeptical when you see for-loops iterating over subviews of cells to hide or even remove views at runtime from the view hierarchy Apple provides you, when there is an easy, versatile, stable and future proof solution right around the corner. 7 little steps is really all you need and they are easy to understand.
我希望当您看到 for 循环迭代单元格的子视图以在运行时从视图层次结构中隐藏甚至删除视图时,您也会持怀疑态度 Apple 为您提供,当有一个简单、多功能、稳定且面向未来的解决方案就在眼前时. 7个小步骤真的是你所需要的,它们很容易理解。
回答by titan
For removing the top and bottom part of separator line for each section. Add this to your static cell.
用于删除每个部分的分隔线的顶部和底部。将此添加到您的静态单元格。
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()
}
}
}
Result as below image
结果如下图
回答by Shad
This is what I finally came up with:
这就是我最终想出的:
I was not able to find some better way than this. But it is working for me greatly. Last tried with Xcode Version 7.3.1 (7D1014). This procedure was done through storyboard.
我找不到比这更好的方法。但它对我很有用。最后尝试使用 Xcode 版本 7.3.1 (7D1014)。这个过程是通过故事板完成的。
Basically I add a UIView of 0.5 pt Height on the UITableViewCell and then set a background color for that UIView. Set parent UITableView's Separator as None.
基本上,我在 UITableViewCell 上添加了一个 0.5 pt 高度的 UIView,然后为该 UIView 设置背景颜色。将父 UITableView 的 Separator 设置为 None。
Here is the details:
以下是详细信息:
Considering you already set your UITableViewCell, custom or default. On the very first stage set the UITableView's separator as None.
考虑到您已经设置了 UITableViewCell,自定义或默认。在第一阶段将 UITableView 的分隔符设置为 None。
Next add a UIView of 1 pt Height and set the Background as you need, on my case it is Red.
接下来添加一个 1 pt 高度的 UIView 并根据需要设置背景,在我的情况下它是红色。
Start setting the constraints. The problem is to set the height of the UIView as 0.5 pt. This is the only Problematic issue for this workflow.
开始设置约束。问题是将 UIView 的高度设置为 0.5 pt。这是此工作流程的唯一有问题的问题。
UIView with 0.5 pt Height:
具有 0.5 pt 高度的 UIView:
Sharing the way to set 0.5 pt height of the UIView.
分享UIView设置0.5pt高度的方法。
First(1) pin the view and then(2) set the height as 0.5. Press Enter.
首先(1)固定视图,然后(2)将高度设置为 0.5。按 Enter。
Finally your UIView will look similar like following.
最后,您的 UIView 将类似于以下内容。
I was not able to set the height as 0.5 other than this way.
除了这种方式,我无法将高度设置为 0.5。
回答by onemanstartup
Here the solution. This is for static cells. If you want dynamic then just rewrite "count". Hope it helps.
这里的解决方案。这是针对静态单元格的。如果你想要动态,那么只需重写“计数”。希望能帮助到你。
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()
}
}
}
}
回答by Art
Tried various solutions based on the cell.separatorInset = UIEdgeInsetsMake()
workaround, none of them working properly.
根据cell.separatorInset = UIEdgeInsetsMake()
解决方法尝试了各种解决方案,但都没有正常工作。
For my iOS11 UITableViewStyleGrouped
based project, this did it:
对于我UITableViewStyleGrouped
基于iOS11的项目,这样做了:
self.tableView.separatorColor = self.tableView.backgroundColor;