[iOS开发]UITableViewStylePlain和UITableViewStyleGrouped样式的区别及效果处理

创建UITableView 时, 需要设置TableView样式, 默认有两种样式:UITableViewStylePlain, UITableViewStyleGrouped

UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) style: UITableViewStyleGrouped]

下面先介绍下, 这两种样式以及区别:

一. UITableView样式介绍

UITableViewStylePlain 介绍

在tableView的UITableViewStylePlain中,当一个section的rows有一部分可见时,section的header和footer浮动在内容顶部。plain style的tableView可以有一个section索引,作为一个bar在table的右边(例如A ~ Z)。你可以点击一个特定的标签,跳转到目标section。
例如下图:

contacts.png

UITableViewStyleGroup 介绍

在tableView的UITableViewStyleGroup中,所有单元格拥有一个默认的背景颜色和默认背景视图。背景视图为特定section中的所有cell提供可视分组。例如,一个group可以是一个人的名字和标题,另一个group可以是电话,电子邮件帐户等。可参考iphone“设置”程序。
例如下图:

settings.png
accessibility.png

Group类型默认设置tableView灰色背景色,cell为白色背景色,section外边缘设置浅灰色边框,cell设置浅灰色间隔线。如下图:

设置.png

二:区别总结:

UITableViewStylePlain使用

1.plain类型有多段时,滚动时Section Header 在顶部停留,有些界面比如设置界面,这些新特性将显得多余。(自带效果)
2.plain类型默认section之间没有中间的间距和头部间距(想让plain类型的section之间留有空白,需要在UITableView代理方法中return自定义的headerView和footerView,并在自定义的headerView 和 footerView 里面重写setFrame方法)

解决方案:让plain类型的UITableView的section头部视图不停留(取消粘性效果)
  • 方法一: 网上好多都是这个方法. 这个代码是通过scroll偏移量来监听和改变你的tableView的contentInset 可见很不好(试试就知道)
//去掉UItableview headerview黏性(sticky)
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat sectionHeaderHeight = 30;
    if (scrollView.contentOffset.y <= sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
        scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
    } else if (scrollView.contentOffset.y >= sectionHeaderHeight) {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
    }
}
  • 方法二: 在自定义section的headerView中, 重写setFrame: 方法来重载table的section.
    • 注意:setFrame方法中需要拿到重载的table和section!
- (void)setFrame:(CGRect)frame {    
    CGRect sectionRect = [self.tableView rectForSection:self.section];
    CGRect newFrame = CGRectMake(CGRectGetMinX(frame), CGRectGetMinY(sectionRect), CGRectGetWidth(frame), CGRectGetHeight(frame)); 
    [super setFrame:newFrame];
}

UITableViewStyleGroup 使用

解决方案:去掉 UITableViewStyleGroup类型的多余间距
应用场景一.png
应用场景一: sction的头部视图和尾部视图,无任何内容
  • 此应用场景需要分两步做:
    第一步: 处理第一个section上边多余间距(2种方法)
  • 方法一: tableView的tableHeaderView属性
    • 注意: 设置tableView头部视图的高度为特小值,但不能为零,若为零的话,iOS会取默认值,就无法消除头部间距了。
- (void)viewDidLoad {
  //设置代理
    tableView.delegate = self;
  //隐藏UITableViewStyleGrouped上边多余的间隔
  tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];
}
  • 方法二: 设置顶部额滚动区域
    tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);
  • 补充: 属性tableHeaderView和contentInset 结合使用, 可以设置表格第一个cell顶到最顶部
  tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];
    tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);

第二步: 处理每个section下边多余间距(2种方法)

  • Group样式, 默认每一组都会有头部和尾部间距, 这两个间距保留一个就可以了.另一个间距设置为0.

  • 方法一: tableView 属性sectionHeaderHeight 和 属性sectionFooterHeight , 处理多余间距

    //设置tableView主间距为20
    tableView.sectionHeaderHeight = 0;
    tableView.sectionFooterHeight = 20;
  • 方法二: 调用tableView的代理方法 , 设置尾部视图的高度,
    • 注意: 去掉的视图, 返回值不能为0,否则系统启用默认值。返回的高度使用极小值CGFLOAT_MIN。
    • 注意2: 调用下面两个tableView代理方法后, sectionHeaderHeight属性和sectionFooterHeight属性设置的值失效.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 44;
}
// 注意:return height 为 0,则 height 被设置成默认值
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return CGFLOAT_MIN;
}
应用场景二.png

应用场景二: sction有头部标题 尾部标题

此应用场景两种方法取其一, 可以同时处理section顶部间距和中间间距

  • 方法一: 设置 tableView 属性sectionHeaderHeight 和 属性sectionFooterHeight , 可同时处理section多余顶部间距和中间间距
tableView.sectionHeaderHeight = 30;
tableView.sectionFooterHeight = 0;
  • 方法二:调用tableView的代理方法 , 设置头部视图和尾部视图的高度
//第二步:隐藏UITableViewStyleGrouped下边多余的间隔
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 30;
}
// 注意:此时可以设置为0
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return 0;
}

应用场景三: section自定义头部视图和尾部视图

  • 调用下面tableView代理方法 自定义头部视图和尾部视图后, 不需要做顶部间距处理, 第一个section头部视图会自动顶到最顶部.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
}
  • 中间间距 只需要通过tableView代理方法, 调整头部视图或者尾部视图各自的高度即可.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 30;
}
//注意:此时可以设置为0
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return 0;
}


三. 在 Storyboard 中 0 代码搞定顶部多余间距

没用 Storyboard 的同学使用上面的代码就 OK 了;
而在 Storyboard 中可以 0 代码搞定这个事:

首先,在第一个 Section 的上面拖进来一个空 UIView

image

然后选中这个 UIView 的 Runtime Attributes 栏,添加一个 frame 的 KeyPath

image

这样头部的间隔就乖乖的不见了:

image
刨根问底 UITableViewHeader 的猫腻

为什么刚才说 0.1 和 CGFLOAT_MIN 是等效的呢?经过研究,这个高度值的影响大概是这样的:

  1. 若传入的 height == 0,则 height 被设置成默认值
  2. 若 height 小于屏幕半像素对应的高度,这个 header 不在另一个像素渲染

半像素也就是 1.0 / scale / 2.0,如在 @2x 屏上是 0.25
直观的感受下,假如这个 height 被设置成 0.5 的样子:

image

导航栏下面的阴影线看上去宽了 0.5 像素的,Done。

参考:
https://www.jianshu.com/p/764ed5aa46cf
http://blog.sina.com.cn/s/blog_801997310102vpa1.html
https://www.cnblogs.com/lurenq/p/8133973.html

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

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

推荐阅读更多精彩内容