[iOS开发]UITableView的分割线设置及不能全屏原因

栏目: IOS · 发布时间: 6年前

内容简介:正是因为layoutMargins是UIView的新增属性,tablet和cell作为UIView的子类都有这个属性,所以相比较iOS7系统,iOS8之后就多了两步,必须同时再对tableView和cell的layoutMargins属性进行处理,才能让分隔线真正全屏.同时官方注释中对preservesSuperviewLayoutMargins(意即:维持父控件的布局边距)属性的说明,也正好能说明网上另一种方法不设置弄清楚了这些原理,就可以更好的记忆和使用这些方法,不用每次都去旧代码查找或者去百度了.
  • 首先先隐藏系统自带的分割线, 接下来有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);
  //绘制高度为2绿色分割线
    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];
    //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 {
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID forIndexPath:indexPath];

   //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 中做法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; 
// 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中:

[iOS开发]UITableView的分割线设置及不能全屏原因

PS:附效果图如下:

设置之前效果图:

[iOS开发]UITableView的分割线设置及不能全屏原因

设置完第1步 self.tableView.separatorInset = UIEdgeInsetsZero; 后效果图:

[iOS开发]UITableView的分割线设置及不能全屏原因

设置完第2步 self.tableView.layoutMargins = UIEdgeInsetsZero; 后效果图:

[iOS开发]UITableView的分割线设置及不能全屏原因

设置完第3步 cell.layoutMargins = UIEdgeInsetsZero; 后效果图:

[iOS开发]UITableView的分割线设置及不能全屏原因

由于笔者水平有限,文中如果有错误的地方,或者有更好的方法,还望大神指出。 附上本文的所有 demo 下载链接, 【GitHub】 。 如果你看完后觉得对你有所帮助,还望在 GitHub 上点个 star。赠人玫瑰,手有余香。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

爆裂

爆裂

[美] 伊藤穰一、[美] 杰夫·豪 / 张培、吴建英、周卓斌 / 中信出版集团 / 2017-9-1 / 65.00元

越是在发生重大改变的时刻,越是会出现两极分化,赢家、输家有时只在一念间。未来已经装上了全新的操作系统。这是一个重大升级,对我们而言,随之而来的则是陡峭的学习曲线。在指数时代,替换旧逻辑,我们的思维亟需与世界对接,推翻过去已经成为大众所接受的常识,学会差异化思考才能屹立不倒,不被卷入历史的洪流。 在《爆裂》一书中,伊藤穰一和杰夫·豪将这一逻辑提炼为9大原则,帮助人们驾驭这一动荡时刻,应对当下的......一起来看看 《爆裂》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具