首先先隐藏系统自带的分割线, 接下来有2种做法 (建议使用做法a)
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.separatorColor = [UIColor clearColor];
做法a: 可以通过addSubview的方式添加一条分割线
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath]
//自定义分割线方法一: 通过addSubview的方式添加一条分割线
//在自定义cell 里面给每个cell添加高度为2的红色分割线
CGFloat cellH = cell.frame.size.height
if(indexPath.row != cars.count - 1){
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, cellH-2, self.view.frame.size.width, 2)]
line.backgroundColor = [UIColor redColor]
[cell addSubview:line]
return cell
做法b:也可以自定义cell, cell中重写drawRect: 自绘分割线
- (void)drawRect:(CGRect)rect
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextFillRect(context, rect);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextStrokeRect(context, CGRectMake(0, rect.size.height - 2, rect.size.width, 2));
复制代码
方法2:自定义cell , 重写setFrame方法,cell高度-1,露出tableView背景色
首先隐藏系统分割线, 设置tableView背景颜色.
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone
// 设置tableView背景色
self.tableView.backgroundColor = [UIColor colorWithWhite:215 / 255.0 alpha:1]
在自定义cell中重写setFrame:
- (void)setFrame:(CGRect)frame
frame.size.height -= 1
// 给cellframe赋值
[super setFrame:frame]
复制代码
方法3.利用系统属性设置(separatorInset, layoutMargins), 共需添加四行代码
对tableView的separatorInset, layoutMargins属性的设置
-(void)viewDidLoad {
[super viewDidLoad];
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
self.tableView.separatorInset = UIEdgeInsetsZero;
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
self.tableView.layoutMargins = UIEdgeInsetsZero;
对cell的LayoutMargins属性的设置
补充:对cell的设置可以写在cellForRowAtIndexPath里,也可以写在willDisplayCell方法里
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];
if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
cell.preservesSuperviewLayoutMargins = NO;
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
return cell;
三种方法优缺点比较:
方法1 中做法a比较好用,可以使用系统自带的cell, 但是需要添加一个view,设置背景颜色和frame. 而做法b仅仅为了分隔线却还必须再自定义cell, 重写drawRect,又显得麻烦;
方法2比较取巧,但是也需要自定义cell,在某些情况下不允许改变tableView的背景色,使用场景有限;
方法3不需要自定义cell,对系统(iOS7,iOS8以上)做个简单判断即可.可惜网上很多文章写的不对,很多人不会正确使用,有些会用的人也说不清楚原理,只管复制粘贴.
比如网上流传的一般是这样,需要四步,虽然真的管用,但多了一步[cell setSeparatorInset:UIEdgeInsetsZero];
而且原理也没讲,估计是某大神写的,根本不屑于过多解释,让我用起来很郁闷,网上流传代码:
首先在viewDidLoad方法中加上如下代码:
-(void)viewDidLoad {
[super viewDidLoad];
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsZero];
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsZero];
然后在willDisplayCell方法中加入如下代码:
- (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];
分割线不能全屏原理解析
其实关于分隔线不能全屏的原理,苹果官方在文件中已经说明了,可以去看一下
在iOS7之前系统默认就是全屏的,iOS7时UITableView
多了separatorInset
属性,可在UITableView
的头文件中查看,如下:
@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR;
iOS7时只要设置该属性为UIEdgeInsetsZero
就没有问题了.
iOS8之后仅仅完成以上设置就不行了,仔细查看后发现iOS8的UIView
的头文件里又多了个layoutMargins
属性,并有官方注释
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
复制代码
正是因为layoutMargins是UIView的新增属性,tablet和cell作为UIView的子类都有这个属性,所以相比较iOS7系统,iOS8之后就多了两步,必须同时再对tableView和cell的layoutMargins属性进行处理,才能让分隔线真正全屏.
同时官方注释中对preservesSuperviewLayoutMargins(意即:维持父控件的布局边距)属性的说明,也正好能说明网上另一种方法不设置self.tableView.layoutMargins = UIEdgeInsetsZero;
而是设置cell.preservesSuperviewLayoutMargins = NO;
为什么也能起作用
弄清楚了这些原理,就可以更好的记忆和使用这些方法,不用每次都去旧代码查找或者去百度了.
说到了最后,不知道大家有没有觉得影响分隔线全屏的元凶layoutMargins属性 稍微有点眼熟呢?其实它在另一个地方也做了不少恶,就在storyboard中:
PS:附效果图如下:
设置之前效果图:
设置完第1步self.tableView.separatorInset = UIEdgeInsetsZero;
后效果图:
设置完第2步self.tableView.layoutMargins = UIEdgeInsetsZero;
后效果图:
设置完第3步cell.layoutMargins = UIEdgeInsetsZero;
后效果图:
由于笔者水平有限,文中如果有错误的地方,或者有更好的方法,还望大神指出。
附上本文的所有 demo 下载链接,【GitHub】。
如果你看完后觉得对你有所帮助,还望在 GitHub 上点个 star。赠人玫瑰,手有余香。