UITableViewCell选中后分割线消失问题

问题:分割线消失了

遇到一个问题,需求是tableview在编辑模式可以多选cell,多选时没有选中背景色,但是有选中按钮🔘。非编辑状态有选中style为灰色。结果发现在选中某个cell时,cell上的分割线消失了。
消失的分割线

自定义cell的时候,我是这么做的,首先将tableView的系统分割线去除

1
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];

然后在cell的初始化方法中自定义了一个UIView,并加到了contentView的底部。其中分割线高度,有些是要求是1像素(不是一个点),所以可以使用 1.0/UIScreen.main.scale 表示一个像素的高度。

1
2
3
4
5
6
7
8
9
UIView *line = [UIView new];
[line setBackgroundColor:[UIColor greenColor]];
[self.contentView addSubview:line];
[line mas_makeConstraints:^(MASConstraintMaker *make){
make.left.equalTo(self.contentView);
make.right.equalTo(self.contentView);
make.height.mas_equalTo(@1);
make.bottom.equalTo(self.contentView);
}];

再然后设置了cell的选中背景为透明

1
2
3
UIView *v = [UIView new];
[v setBackgroundColor:[UIColor clearColor]];
[self setSelectedBackgroundView:v];

完美实现,既可以自定义分割线,又可以自定义选中背景颜色,很灵活。

分析:消失的原因

但是,为什么选中后分割线消失了?而且只是分割线消失了,cell上的其他label、button都还在。
看视图的层次图,发现并不是SelectedBackgroundView挡住了分割线,也不是约束问题导致分割线被挤出了可视范围。
首先是觉得SelectedBackgroundView出了问题,就自定义SelectedBackgroundView为带有分割线的view,再设置为SelectedBackgroundView,发现问题解决了。
然而,分割线在编辑状态和非编辑状态的leading约束是不一样的,手动设置55(40+15,原cell的分割线leading是15)发现iPhone上可以对齐,但是在ipad上测试是发现了其他问题:有些cell上分割线还是消失了。
失灵的解决方法

很显然,解决问题的方向错了。
我故意加了另一个很大的很蓝的view,看是否还不显示。结果这个很大很蓝的view在选中时仍不显示。再次查看层次图,放大发现被选中的cell的分割线背景色是w:0 a:0,其他cell的是正常的。
背景色没了
OK,还是百度一下,原来并非是分割线消失了,而是contentView上所有的view的背景颜色被清除了,或者说被设置成透明了。包括UIView以及所有基于UIView的UILabel等。

分析:解决方法

那如何解决该问题?既然在选中的时候被系统清空了cell上的view的背景色,那么只需要再设置回来就好了。
1. 重写cell的setSelected方法,恢复分割线的颜色

1
2
3
4
-(void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
[line setBackgroundColor:[UIColor greenColor]];
}

这个方法就更加灵活了,还可以根据你的选中状态,分别设置不同的颜色。

那么问题来了,既然是选中时,系统默认清除了所有子控件的背景色,那么我不实现父类的方法可不可以?

1
2
3
4
-(void)setSelected:(BOOL)selected animated:(BOOL)animated {
//[super setSelected:selected animated:animated];
//我不实现super的选中方法,那是不是就不会自动清除颜色了呢?
}

结果证明我依旧想多了。不实现super的选中方法,cell将不会保持选择状态,但是点上去的时候,依旧会清除掉子控件的背景色。

有人说把分割线加在cell上而不是contentview上可以解决,实际测试结果:直接加在cell上仍然是会被清除背景色

2. 使用imageView
创建一个imageView,让UI给图,或者通过颜色创建一个图片,设置imageView的图片,就不存在由于背景色被清理而没有分割线的问题了。
3. 给这个分割线单独定义个类
比如:GlobleSeparatorLine,只需要在xib或者storyboard里,更改分割线的类型为GlobleSeparatorLine。然后重写layoutSubviews,在方法里设置背景颜色即可。