问题剖析:UITableViewCell选中后背景消失
在自定义UITableView时,我发现一个奇怪的现象:当我选择某个cell时,cell上自定义的分割线消失了。
我是这么做的,首先将tableView的系统分割线去除
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
然后在cell的初始化方法中自定义了一个UIView,并加到了contentView的底部
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的选中背景为透明
UIView *v = [UIView new];
[v setBackgroundColor:[UIColor clearColor]];
[self setSelectedBackgroundView:v];
完美实现,既可以自定义分割线,又可以自定义选中背景颜色,很灵活。
但是,为什么选中后分割线消失了?而且只是分割线消失了,cell上的其他label、button都还在。
经过试验分析,我发现并非是分割线消失了,而是contentView上所有的view的背景颜色被清除了,或者说被设置成透明了。包括UIView以及所有基于UIView的UILabel等。
那如何解决该问题,我提出以下三种方法:
1.设置cell为不可选的
[self setSelectionStyle:UITableViewCellSelectionStyleNone];
该方法最为简单,可以实现点击后背景颜色不变的需求。但是不灵活。
cell将不能被选中,自然不能自由控制选中的效果,也就避免了被选中时颜色被清除的问题。
2.重写cell上控件的setBackgroundColor方法
@interface CustomView : UIView
- (void)setCustomBackgroundColor:(UIColor*)color;
@end
@implementation CustomView
- (void) setCustomBackgroundColor:(UIColor*)color {
super.backgroundColor = color;
}
- (void)setBackgroundColor:(UIColor *)color {
//空实现,系统清空背景色时会调到此处
}
@end
该方法可靠,也较灵活,就是麻烦了点,得重写所有有背景色的view。
3.重写cell的setSelected方法
-(void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
[line setBackgroundColor:[UIColor greenColor]];
}
这个方法就更加灵活了,还可以根据你的选中状态,分别设置不同的颜色。
那么问题来了,既然是选中时,系统默认清除了所有子控件的背景色,那么我不实现父类的方法可不可以?
-(void)setSelected:(BOOL)selected animated:(BOOL)animated {
//[super setSelected:selected animated:animated];
//我不实现super的选中方法,那是不是就不会自动清除颜色了呢?
}
结果证明我依旧想多了。不实现super的选中方法,cell将不会保持选择状态,但是点上去的时候,依旧会清除掉子控件的背景色。
留下的尾巴是:系统究竟是怎么实现选中时自动清除子控件背景色的?
大神们留下了一些有意思的方法,我去试着理解了一下。
直接将线加在cell
[self setBackgroundColor:[UIColor whiteColor]];
UIView *v = [UIView new];
[v setBackgroundColor:[UIColor grayColor]];
[self setSelectedBackgroundView:v];
[self.contentView setBackgroundColor:[UIColor brownColor]];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make){
make.left.and.top.and.right.equalTo(self);
make.bottom.equalTo(self).offset(-10);
}];
line = [UIView new];
[line setBackgroundColor:[UIColor greenColor]];
[self addSubview:line];
[line mas_makeConstraints:^(MASConstraintMaker *make){
make.left.and.bottom.and.right.equalTo(self);
make.height.mas_equalTo(5);
}];
最终的效果是
gif.gif
可以看到,在contentView之外的自定义UIView的背景色仍然被清除了。
是我的理解还没到位吗?