去掉 UITableView 顶部的多余空间

将 UITableView 的 style 设为 grouped 后发现顶部出现了大约有35px的额外空白。

原因是 group 样式的 UITableView 顶部会生成自带初始高度的 tableHeaderView。解决方案将 tableHeaderView 替换成一个高度为0的 UIView。首先尝试将高度设为 CGRectZero:

// 这种写法有问题
UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectZero];
self.tableView.tableHeaderView = tableViewHeaderView;

另外,如果 UITableView 充满了整个 ViewController 的垂直空间,还需要添加下面这行代码,禁止 ViewController 自动调整 ScrollView Insets:

self.automaticallyAdjustsScrollViewInsets = NO;

使用上面这种写法,视图初始化之后看似正常,但由于实际上 tableHeaderView 不接受0作为高度,在进行页面滚动之后可能会现现问题。

正确的写法是将高度设为一个很小但不为0的数值。

// 正确的写法
UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.tableView.bounds.size.width, CGFLOAT_MIN)];
self.tableView.tableHeaderView = tableViewHeaderView;

上面代码中使用了 CGFLOAT_MIN,表示浮点数的最小值。写成 0.01f 这样的数值也可以,但不如上面的写法来得自然。

不论这种情况算不算是 Bug,至少算是一种 unexpected behaviour。网上可以搜到的另外一种解决方法,是将 UITableView 顶部的 contentInset 设为负值。

self.tableView.contentInset = UIEdgeInsetsMake(-36, 0, 0, 0);

这并不是一种好的方案。首先,-36只是一个经验值,并不适用于所有机型,特别是那些还未发布的机型。另外,如果 Apple 在将来改变了 UITableView 的这一行为,把 contentInset 设为负值会带来新的问题,将 tableHeaderView 设为0就不存在这样的风险。

还是有问题?

可以参考这个问题下的讨论,设置 edgesForExtendedLayoutextendedLayoutIncludesOpaqueBarsautomaticallyAdjustsScrollViewInsets 这三个属性的不同组合吧。

参考