我有一个应用程序,UITableView
'的分隔符被设置为自定义值 - 右边0
,左边0
。这在 "iOS 7.x "中运行良好,但在 "iOS 8.0 "中,我看到分隔器的嵌入被设置为右侧的默认值 "15"。即使在xib文件中设置为`0',它仍然显示不正确。
我如何删除UITableViewCell
的分隔符?
**iOS 8.0在单元格和表格视图上引入了 layoutMargins 属性。
这个属性在iOS 7.0上是不可用的,所以你需要确保在分配它之前进行检查!
简单的解决方法是按照@user3570727的建议,对单元格进行子类化并覆盖布局边距属性。但是你会失去任何系统行为,比如从安全区域继承边距,所以我不推荐下面的解决方案。
(ObjectiveC)
-(UIEdgeInsets)layoutMargins {
return UIEdgeInsetsZero // override any margins inc. safe area
}
(Swift 4.2):
override var layoutMargins: UIEdgeInsets { get { return .zero } set { } }
如果你不想覆盖该属性,或者需要有条件地设置它,请继续阅读。
除了 "layoutMargins "属性外,苹果还为你的单元格添加了一个**属性,可以防止它继承你的表视图的边距设置。当这个属性被设置后,你的单元格被允许独立于表视图来配置自己的边距。可以把它看作是一种覆盖。
这个属性被称为preservesSuperviewLayoutMargins',将其设置为
NO'将允许单元格的layoutMargin'设置覆盖你的表视图上的任何
layoutMargin'。这既节省了时间(你不需要修改表视图的设置),又更简洁。请参考Mike Abdullah的回答以获得详细解释。
*注意:下面是对**单元格级边距设置的简洁实现,正如Mike Abdullah的回答所表达的那样。设置你的单元格的preservesSuperviewLayoutMargins=NO
将确保你的表视图不会覆盖单元格的设置。如果你真的希望你的整个表视图有一致的边距,请相应地调整你的代码。
设置你的单元格边距:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove seperator inset
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
// 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:UIEdgeInsetsZero];
}
}
快速4:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// Remove seperator inset
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
// Prevent the cell from inheriting the Table View's margin settings
if cell.responds(to: #selector(setter: UITableViewCell.preservesSuperviewLayoutMargins)) {
cell.preservesSuperviewLayoutMargins = false
}
// Explictly set your cell's layout margins
if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
cell.layoutMargins = .zero
}
}
将单元格上的 "preservesSuperviewLayoutMargins "属性设置为NO,**应该可以防止表格视图覆盖单元格的边距。在某些情况下,它似乎不能正常工作。
如果一切都失败了,你可以用暴力强制你的表视图页边距:
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Force your tableview margins (this may be a bad idea)
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
}
}
快速4:
func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Force your tableview margins (this may be a bad idea)
if tableView.responds(to: #selector(setter: UITableView.separatorInset)) {
tableView.separatorInset = .zero
}
if tableView.responds(to: #selector(setter: UITableView.layoutMargins)) {
tableView.layoutMargins = .zero
}
}
...然后你就可以了! 这应该可以在iOS 7和8上使用。
编辑:Mohamed Saleh让我注意到iOS 9中的一个可能的变化。**如果你想定制内嵌或边距,你可能需要将表视图的cellLayoutMarginsFollowReadableWidth
设置为NO
。你的情况可能有所不同,这一点没有很好的记录。
这个属性只存在于iOS 9中,所以在设置前一定要检查。
Swift 4:
if myTableView.responds(to: #selector(setter: self.cellLayoutMarginsFollowReadableWidth)) {
myTableView.cellLayoutMarginsFollowReadableWidth = false
}
(以上代码来自https://stackoverflow.com/questions/25770119/ios-8-uitableview-separator-inset-0-not-working/32860532#32860532)
编辑:这里有一个纯界面生成器的方法:
![TableViewAttributesInspector][1]。 ![TableViewCellSizeInspector][2]。
注意:iOS 11改变并简化了这一行为的大部分内容,即将进行更新...。
让我们在盲目地冲进去试图修复它之前,先花点时间了解一下这个问题。
在调试器中快速戳一下会告诉你,分隔线是UITableViewCell
的子视图。
看来,单元格本身对这些线条的布局承担了相当大的责任。
iOS 8引入了布局边距的概念。
默认情况下,一个视图'的布局边距在所有边上都是8pt
,它们'是从祖先视图中*继承的。
据我们所知,在布局其分隔线时,UITableViewCell
选择尊重左侧布局边距,用它来约束左侧插页。
综合这些,要想实现真正零的插页,我们需要。
0
。这样说来,要实现这个任务很简单。
cell.layoutMargins = UIEdgeInsetsZero;
cell.preservesSuperviewLayoutMargins = NO;
需要注意的事情。
preservesSuperviewLayoutMargins
指定一个用户定义的运行时属性。preservesSuperviewLayoutMargins
相比,你可以配置祖先视图(如表格)也有0
左边距,但这似乎本质上更容易出错,因为你不控制整个层次结构。0
,其他的都不设置,可能会更简洁一些。UITableView
在普通样式表的底部绘制,我猜想这也需要在表层指定相同的设置(还没试过这个!)。我相信这也是我在这里提出的问题:https://stackoverflow.com/questions/25762723/remove-separatorinset-on-ios-8-uitableview-for-xcode-6-iphone-simulator。
在iOS 8中,所有继承自UIView
的对象都有一个新属性。所以,在iOS7.x中设置SeparatorInset
的方案将无法去除你在iOS8中看到的UITableView上的白色空间。
新的属性被称为"layoutMargins"。
@property(nonatomic) UIEdgeInsets layoutMargins
Description The default spacing to use when laying out content in the view.
Availability iOS (8.0 and later)
Declared In UIView.h
Reference UIView Class Reference
解决办法:-
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
if ([tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[tableView setSeparatorInset:UIEdgeInsetsZero];
}
if ([tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[tableView setLayoutMargins:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
如果你设置cell.layoutMargins = UIEdgeInsetsZero;
而不检查layoutMargins
是否存在,在iOS 7.x上应用程序会崩溃。
您可以在应用程序启动时(在UI加载之前)使用一次UIAppearance,将其设置为默认的全局设置。
// iOS 7:
[[UITableView appearance] setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
[[UITableView appearance] setSeparatorInset:UIEdgeInsetsZero];
[[UITableViewCell appearance] setSeparatorInset:UIEdgeInsetsZero];
// iOS 8:
if ([UITableView instancesRespondToSelector:@selector(setLayoutMargins:)]) {
[[UITableView appearance] setLayoutMargins:UIEdgeInsetsZero];
[[UITableViewCell appearance] setLayoutMargins:UIEdgeInsetsZero];
[[UITableViewCell appearance] setPreservesSuperviewLayoutMargins:NO];
}
这样,你可以保持你的UIViewController'的代码干净,如果你想的话,可以随时覆盖它。
**iOS在单元格和表格视图上引入了layoutMargins属性。
这个属性在iOS 7.0中是不可用的,所以你需要在分配它之前确认一下!不过,苹果已经为你的单元格和表格视图添加了属性,叫做preservesSuperviewLayoutMargins。
然而,Apple已经为你的单元格添加了一个名为preservesSuperviewLayoutMargins的**属性,这将防止它继承你的表视图'的边距设置。 这样,你的单元格就可以独立于表视图配置自己的边距。 可以把它看作是一个覆盖。
这个属性叫做preservesSuperviewLayoutMargins,将它设置为NO可以让你用自己单元格的layoutMargin设置覆盖你的Table View'的layoutMargin设置。 这既节省了时间(你不必修改表视图的设置),也更简洁。 详细解释请参考Mike Abdullah'的回答。
*注意:这才是正确的、不那么乱的方法。 这是正确的、不那么混乱的实现方式,正如Mike Abdullah'的回答中所表达的那样。 设置单元格'的 preservesSuperviewLayoutMargins=NO 将确保你的表视图不会覆盖单元格设置。
第一步 - 设置单元格的边距:。
/*
Tells the delegate that the table view is about to draw a cell for a particular row.
*/
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,
forRowAtIndexPath indexPath: NSIndexPath)
{
// Remove separator inset
if cell.respondsToSelector("setSeparatorInset:") {
cell.separatorInset = UIEdgeInsetsZero
}
// Prevent the cell from inheriting the Table View's margin settings
if cell.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
cell.preservesSuperviewLayoutMargins = false
}
// Explictly set your cell's layout margins
if cell.respondsToSelector("setLayoutMargins:") {
cell.layoutMargins = UIEdgeInsetsZero
}
}
将单元格上的 preservesSuperviewLayoutMargins 属性设置为 NO 应该可以防止表格视图覆盖单元格的边距。 在某些情况下,它似乎不能正常工作。
第二步--只有当所有步骤都失败时,您才可以强制执行您的表格视图页边距:。
/*
Called to notify the view controller that its view has just laid out its subviews.
*/
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// Force your tableview margins (this may be a bad idea)
if self.tableView.respondsToSelector("setSeparatorInset:") {
self.tableView.separatorInset = UIEdgeInsetsZero
}
if self.tableView.respondsToSelector("setLayoutMargins:") {
self.tableView.layoutMargins = UIEdgeInsetsZero
}
}
......然后就可以了! 这应该适用于iOS 8以及iOS 7。
请注意。 使用iOS 8.1和7.1进行测试,在我的情况下,我只需要使用本解释的第一步。
第二步只有当你的渲染单元格下面有未填充的单元格时才需要,即。 如果表的行数大于表模型中的行数。 不做第二步会导致分隔符偏移量不同。
对于iOS 9,你需要添加。
if([myTableView respondsToSelector:@selector(setCellLayoutMarginsFollowReadableWidth:)])
{
myTableView.cellLayoutMarginsFollowReadableWidth = NO;
}
详情请见【问题】(https://stackoverflow.com/a/31538250/3151066)。
Swift 2.0扩展
我只是想分享一下我做的一个扩展,以去除tableview单元格分隔符的边距。
extension UITableViewCell {
func removeMargins() {
if self.respondsToSelector("setSeparatorInset:") {
self.separatorInset = UIEdgeInsetsZero
}
if self.respondsToSelector("setPreservesSuperviewLayoutMargins:") {
self.preservesSuperviewLayoutMargins = false
}
if self.respondsToSelector("setLayoutMargins:") {
self.layoutMargins = UIEdgeInsetsZero
}
}
}
用于上下文:。
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell
cell.removeMargins()
return cell
斯威夫特。
override func viewDidLoad() {
super.viewDidLoad()
if self.tableView.respondsToSelector("setSeparatorInset:") {
self.tableView.separatorInset = UIEdgeInsetsZero
}
if self.tableView.respondsToSelector("setLayoutMargins:") {
self.tableView.layoutMargins = UIEdgeInsetsZero
}
self.tableView.layoutIfNeeded() // <--- this do the magic
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
...
if cell.respondsToSelector("setSeparatorInset:") {
cell.separatorInset = UIEdgeInsetsZero
}
if cell.respondsToSelector("setLayoutMargins:") {
cell.layoutMargins = UIEdgeInsetsZero
}
return cell
}
至于cdstamper的建议,在单元格的layoutSubview方法中添加以下几行,而不是表格视图。
- (void)layoutSubviews
{
[super layoutSubviews];
if ([self respondsToSelector:@selector(setSeparatorInset:)])
[self setSeparatorInset:UIEdgeInsetsZero];
if ([self respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)])
{
[self setPreservesSuperviewLayoutMargins:NO];;
}
if ([self respondsToSelector:@selector(setLayoutMargins:)])
{
[self setLayoutMargins:UIEdgeInsetsZero];
}
}
Swift 3.0示例:。
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// removing seperator inset
if cell.responds(to: #selector(setter: UITableViewCell.separatorInset)) {
cell.separatorInset = .zero
}
// prevent the cell from inheriting the tableView's margin settings
if cell.responds(to: #selector(setter: UIView.preservesSuperviewLayoutMargins)) {
cell.preservesSuperviewLayoutMargins = false
}
// explicitly setting cell's layout margins
if cell.responds(to: #selector(setter: UITableViewCell.layoutMargins)) {
cell.layoutMargins = .zero
}
}
这是唯一能完全控制这些东西的方法(我可以找到)。
要完全控制每个单元格的分隔符插入和布局边距。 在你的 "UITableviewDelegate "上的 "willDisplayCell "方法中这样做。
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
cell.layoutMargins = UIEdgeInsetsZero
cell.contentView.layoutMargins = UIEdgeInsetsMake(0, 10, 0, 10)
cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
}
单元格对象控制分隔符,而contentView
控制其他一切。
如果你的分隔符插入的空格显示的颜色出乎意料,这应该可以解决这个问题。
cell.backgroundColor = cell.contentView.backgroundColor
在iOS 8的Swift中使用自定义的 "UITableViewCell "的简单解决方案。
override func awakeFromNib() {
super.awakeFromNib()
self.layoutMargins = UIEdgeInsetsZero
self.separatorInset = UIEdgeInsetsZero
}
通过这种方式,你只需设置layoutMargin
和separatorInset
一次,而不是像上面大多数答案所建议的那样,为每个willDisplayCell
设置。
如果你使用的是自定义的UITableViewCell
,这是正确的地方。
否则你应该在tableView:cellForRowAtIndexPath
中做。
只是另一个提示。
你不需要设置preservesSuperviewLayoutMargins=false
,因为默认值已经是NO
了!
只要加上下面的代码就可以解决这个程序。
祝您好运!
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
。
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
卢卡兹用Swift回答。
// iOS 7:
UITableView.appearance().separatorStyle = .SingleLine
UITableView.appearance().separatorInset = UIEdgeInsetsZero
UITableViewCell.appearance().separatorInset = UIEdgeInsetsZero
// iOS 8:
if UITableView.instancesRespondToSelector("setLayoutMargins:") {
UITableView.appearance().layoutMargins = UIEdgeInsetsZero
UITableViewCell.appearance().layoutMargins = UIEdgeInsetsZero
UITableViewCell.appearance().preservesSuperviewLayoutMargins = false
}
这是我在Swift中使用的代码。
override func viewDidLoad()
{
super.viewDidLoad()
...
if tableView.respondsToSelector("setSeparatorInset:") {
tableView.separatorInset = UIEdgeInsetsZero
}
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath)
{
if cell.respondsToSelector("setSeparatorInset:") {
cell.separatorInset.left = CGFloat(0.0)
}
if tableView.respondsToSelector("setLayoutMargins:") {
tableView.layoutMargins = UIEdgeInsetsZero
}
if cell.respondsToSelector("setLayoutMargins:") {
cell.layoutMargins.left = CGFloat(0.0)
}
}
对我来说,这似乎是最简洁的(目前),因为所有的单元格/tableView边缘/边距调整都是在tableView:willDisplayCell:forRowAtIndexPath:
方法中完成的,而不需要将不必要的代码塞进tableView:cellForRowAtIndexPath:
中。
顺便说一下,我只设置了单元格的左分隔符Inset/layoutMargins,因为在这种情况下,我不想搞砸我在单元格中设置的约束。
代码已更新至Swift 2.2:。
override func viewDidLoad() {
super.viewDidLoad()
if tableView.respondsToSelector(Selector("setSeparatorInset:")) {
tableView.separatorInset = UIEdgeInsetsZero
}
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell,forRowAtIndexPath indexPath: NSIndexPath) {
if cell.respondsToSelector(Selector("setSeparatorInset:")) {
cell.separatorInset.left = CGFloat(0.0)
}
if tableView.respondsToSelector(Selector("setLayoutMargins:")) {
tableView.layoutMargins = UIEdgeInsetsZero
}
if cell.respondsToSelector(Selector("setLayoutMargins:")) {
cell.layoutMargins.left = CGFloat(0.0)
}
}
大多数答案都显示单元格和tableviews的分隔符插入和布局边距被设置在各种方法上(即viewDidLayoutSubviews
、willDisplayCell
等),但我发现只要把这些放在cellForRowAtIndexPath
中就可以了。
似乎是最简洁的方式。
// kill insets for iOS 8
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8) {
cell.preservesSuperviewLayoutMargins = NO;
[cell setLayoutMargins:UIEdgeInsetsZero];
}
// iOS 7 and later
if ([cell respondsToSelector:@selector(setSeparatorInset:)])
[cell setSeparatorInset:UIEdgeInsetsZero];