UITableView设置全屏分隔线的几种方法比较


一般TableView设置全屏分隔线有下面三种方法

1.自定义cell,手动添加分割线

  • 隐藏自带的
    tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

  • 可以通过addSubview的方式添加一条分割线;也可以自绘分割线。

// 自绘分割线
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextFillRect(context, rect);
    
    CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:0xE2/255.0f green:0xE2/255.0f blue:0xE2/255.0f alpha:1].CGColor);
    CGContextStrokeRect(context, CGRectMake(0, rect.size.height - 1, rect.size.width, 1));
}

2.重写cell的setFrame方法,高度-1,露出背景色

- (void)setFrame:(CGRect)frame
{
    frame.size.height -= 1;
    // 给cellframe赋值
    [super setFrame:frame];
}
  • 取消系统的分割线
  • 设置tableView背景色为分割线颜色
 // 取消系统分割线
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    // 设置tableView背景色
    self.tableView.backgroundColor = [UIColor colorWithWhite:215 / 255.0 alpha:1];

3.利用系统属性设置(separatorInset, layoutMargins)共需添加三句代码:

  • 对tableView的separatorInset, layoutMargins属性的设置
-(void)viewDidLoad {
    [super viewDidLoad];
    //1.调整(iOS7以上)表格分隔线边距
    if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
        self.tableView.separatorInset = UIEdgeInsetsZero;
    }
    //2.调整(iOS8以上)view边距(或者在cell中设置preservesSuperviewLayoutMargins,二者等效)
    if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
        self.tableView.layoutMargins = UIEdgeInsetsZero;
    }
}
  • 对cell的LayoutMargins属性的设置
对cell的设置可以写在cellForRowAtIndexPath里,也可以写在willDisplayCell方法里

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *ID = @"cell";
    FSDiscoverSpecialCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[FSDiscoverSpecialCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }

   //2.调整(iOS8以上)tableView边距(与上面第2步等效,二选一即可)
    if ([cell respondsToSelector:@selector(setPreservesSuperviewLayoutMargins:)]) {
        cell.preservesSuperviewLayoutMargins = NO;
    }
   //3.调整(iOS8以上)view边距
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
    return cell;
}

三种方法优缺点比较:

  • 方法1是比较好用的,但是有些情况下系统自带的cell就足够用了,仅仅为了分隔线却还必须再自定义cell,添加一个view,设置背景颜色和frame,又显得麻烦;

  • 方法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; 
// allows customization of the frame of cell separators

iOS7时只要设置该属性为UIEdgeInsetsZero就没有问题了.


iOS8之后仅仅完成以上设置就不行了,仔细查看后发现iOS8的UIView
的头文件里又多了个layoutMargins属性,并有官方注释

@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
/*
 -layoutMargins returns a set of insets from the edge of the view's bounds that denote a default spacing for laying out content.
 If preservesSuperviewLayoutMargins is YES, margins cascade down the view tree, adjusting for geometry offsets, so that setting the left value of layoutMargins on a superview will affect the left value of layoutMargins for subviews positioned close to the left edge of their superview's bounds
 If your view subclass uses layoutMargins in its layout or drawing, override -layoutMarginsDidChange in order to refresh your view if the margins change.
 */
大意是说:layoutMargins是view的bounds的边距,用来调整内容默认边距

如果preservesSuperviewLayoutMargins属性是YES,那么设置父控件的layoutMargins边距,
就会影响所有子控件的相对于父控件bounds的layoutMargins边距

如果你的view的子类在布局或者绘图中使用了layoutMargins属性,需要重写-layoutMarginsDidChange 方法,
以便当边距改变时能刷新你的view

正是因为layoutMargins是UIView的新增属性,tablet和cell作为UIView的子类都有这个属性,所以相比较iOS7系统,iOS8之后就多了两步,必须同时再对tableView和cell的layoutMargins属性进行处理,才能让分隔线真正全屏.

同时官方注释中对preservesSuperviewLayoutMargins(意即:维持父控件的布局边距)属性的说明,也正好能说明网上另一种方法不设置self.tableView.layoutMargins = UIEdgeInsetsZero;而是设置cell.preservesSuperviewLayoutMargins = NO;为什么也能起作用

弄清楚了这些原理,就可以更好的记忆和使用这些方法,不用每次都去旧代码查找或者去百度了.

说到了最后,不知道大家有没有觉得影响分隔线全屏的元凶layoutMargins属性 稍微有点眼熟呢?其实它在另一个地方也做了不少恶,就在storyboard中:

QQ20150413-000@2x.png


PS:附效果图如下:


设置之前效果图:

QQ20150411-111@2x.png

设置完第1步self.tableView.separatorInset = UIEdgeInsetsZero;后效果图:
QQ20150411-222@2x.png

设置完第2步self.tableView.layoutMargins = UIEdgeInsetsZero;后效果图:
QQ20150411-333@2x.png

设置完第3步cell.layoutMargins = UIEdgeInsetsZero;后效果图:
QQ20150411-444@2x.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容