iOS UITableViewStylePlain和UITabl
创建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。
例如下图:
UITableViewStyleGroup 介绍
在tableView的UITableViewStyleGroup中,所有单元格拥有一个默认的背景颜色和默认背景视图。背景视图为特定section中的所有cell提供可视分组。例如,一个group可以是一个人的名字和标题,另一个group可以是电话,电子邮件帐户等。可参考iphone“设置”程序。
例如下图:
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刨根问底 UITableViewHeader 的猫腻
为什么刚才说 0.1 和 CGFLOAT_MIN 是等效的呢?经过研究,这个高度值的影响大概是这样的:
- 若传入的 height == 0,则 height 被设置成默认值
- 若 height 小于屏幕半像素对应的高度,这个 header 不在另一个像素渲染
半像素也就是 1.0 / scale / 2.0
,如在 @2x 屏上是 0.25
直观的感受下,假如这个 height 被设置成 0.5 的样子:
导航栏下面的阴影线看上去宽了 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。赠人玫瑰,手有余香。