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


通常TableView设置全屏分隔线有下面三种方法ide

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

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

  • 能够经过addSubview的方式添加一条分割线;也能够自绘分割线。atom

// 自绘分割线
- (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,露出背景色spa

- (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)共需添加三句代码:code

  • 对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,又显得麻烦;cdn

  • 方法2比较取巧,可是也须要自定义cell,在某些状况下不容许改变tableView的背景色,使用场景有限;blog

  • 方法3不须要自定义cell,对系统(iOS7,iOS8以上)作个简单判断便可.惋惜网上不少文章写的不对,不少人不会正确使用,有些会用的人也说不清楚原理,只管复制粘贴. 好比网上流传的通常是这样,须要四步,虽然真的管用,但多了一步[cell setSeparatorInset:UIEdgeInsetsZero];并且原理也没讲,估计是某大神写的,根本不屑于过多解释,让我用起来很郁闷,网上流传代码:ci

首先在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];
    }
}
复制代码

其实关于分隔线不能全屏的原理,苹果官方在文件中已经说明了,能够去看一下string


在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
相关文章
相关标签/搜索