更改UITableView节标题的默认滚动行为

我有一个UITableView有两个部分。 这是一个简单的表格视图。 我使用viewForHeaderInSection为这些标题创build自定义视图。 到现在为止还挺好。

默认的滚动行为是当遇到一个节时,节标题停留在导航栏下方,直到下一节滚动到视图中。

我的问题是这样的:我可以改变默认的行为,使节标题不停留在顶部,而是滚动下导航栏的其余部分的行?

我错过了什么明显的?

谢谢。

我解决这个问题的方法是根据UITableViewControllerDelegate (extends UIScrollViewDelegate )中的contentInset来调整contentOffset ,如下所示:

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat sectionHeaderHeight = 40; 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); } } 

这里唯一的问题是,当滚动回顶部时,它会有一点反弹。


{注:“40”应该是你的部分0头的确切高度。 如果您使用的数字大于第0节标题高度,则会看到手指感受受到影响(尝试像“1000”一样,您会看到顶部的反弹行为有点奇怪)。 如果这个数字与你的第0节头部高度相符,手指的感觉似乎是完美的或近乎完美的。}

您还可以在顶部添加一个零行的部分,并简单地使用前一部分的页脚作为下一个的标题。

如果我这样做,我会利用平原风格的UITableViews有粘滞的标题和分组风格的不要。 我可能至less会尝试使用自定义表格单元格来模仿分组表格中的纯单元格的外观。

我实际上没有尝试过,所以它可能无法正常工作,但这就是我所build议的。

我知道它迟到了,但我find了最终的解决scheme!

你想要做的是如果你有10个部分,让dataSource返回20.节的标题使用偶数,节的内容使用奇数。 像这样的东西

 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section%2 == 0) { return 0; }else { return 5; } } -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if (section%2 == 0) { return [NSString stringWithFormat:@"%i", section+1]; }else { return nil; } } 

瞧! :d

有几件事情需要做,以非hacky的方式来解决这个问题:

  1. 将表视图样式设置为UITableViewStyleGrouped
  2. 将表格视图backgroundColor设置为[UIColor clearColor]
  3. 使用backgroundView将每个表视图单元格上的backgroundView设置为空视图backgroundColor [UIColor clearColor]
  4. 如果需要,可以适当地设置表视图rowHeight ,或者覆盖tableView:heightForRowAtIndexPath:如果单个行具有不同的高度。

最初发布在这里 ,使用IB的快速解决scheme。 尽pipe相当简单,但可以通过编程来完成。

一个可能更简单的方法来实现这个(使用IB):

拖动一个UIView到你的TableView,使其成为它的标题视图。

  1. 将该标题视图高度设置为100px
  2. 将tableview contentInset(顶部)设置为-100
  3. 节标题现在将像任何常规单元格一样滚动。

有人评论说,这个解决scheme隐藏了第一个标题,但我没有注意到任何这样的问题。 它对我来说是完美的,迄今为止我所见过的最简单的解决scheme。

到目前为止,我对这里所描述的解决scheme并不满意,所以我试图把它们结合起来。 结果是下面的代码,由@awulf和@cescofry启发。 它适用于我,因为我没有真正的表视图标题。 如果您已经有了表格视图标题,则可能需要调整高度。

 // Set the edge inset self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0); // Add a transparent UIView with the height of the section header (ARC enabled) [self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]]; 

只要改变TableView风格:

 self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

UITableViewStyle文档 :

UITableViewStylePlain-一个普通的表格视图。 任何节标题或页脚显示为行内分隔符,并在滚动表视图时浮动。

UITableViewStyleGrouped – 一个表视图,其各节显示不同的行组。 部分页眉和页脚不会浮动。

改变你的TableView风格:

 self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

根据UITableView的苹果文档:

UITableViewStylePlain-一个普通的表格视图。 任何节标题或页脚显示为行内分隔符,并在滚动表视图时浮动。

UITableViewStyleGrouped – 一个表视图,其各节显示不同的行组。 部分页眉和页脚不会浮动。 希望这个小小的改变会帮助你..

使用截面视图中标题的高度相同的透明视图设置表格的headerView。 同时用ay框架启动tableview – 高度。

 self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)]; UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease]; [self.tableView setTableHeaderView:headerView]; 

我find了一个替代解决scheme,使用每个部分的第一个单元而不是一个真正的标题部分,这个解决scheme看起来不那么干净,但工作得很好,您可以使用定义的原型单元格为您的标题部分,并在方法cellForRowAtIndexPath请求indexPath.row == 0,如果为true,则使用标题部分的原型单元格,否则使用默认的原型单元格。

选择分组的TableView风格

从故事板中的tableView属性检查器中select分组表视图样式。

现在,分组样式看起来基本上与iOS 7中的平面样式(在平坦度和背景方面)相同,对于我们来说,最好的和最简单的(即最简单的)修复就是简单地将表视图的样式更改为分组。 当我们在顶部集成一个滚动的导航栏时,用contentInsets顶起来总是一个问题。 使用分组表格视图样式,它看起来完全相同(与我们的单元格)和节头保持不变。 没有滚动奇怪。

为您的tableView指定一个负插入。 如果你有22px的高段头,你不希望它们粘滞,你reloadData后添加:

 self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

对我来说就像一个魅力。 同样适用于页脚,只需在底部指定负片即可。

我将表添加到滚动视图,似乎很好。

在这里检查我的答案。 这是实现非浮动节头的最简单的方法,没有任何黑客。

@ LocoMike的答案最好适合我的tableView,但它也打破了使用页脚。 所以,这是使用页眉和页脚时更正的解决scheme:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return (self.sections.count + 1) * 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section % 3 != 1) { return 0; } section = section / 3; ... } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { if (section % 3 != 0) { return nil; } section = section / 3; ... } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section % 3 != 0) { return 0; } section = section / 3; ... } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { if (section % 3 != 2) { return 0; } section = section / 3; ... } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section % 3 != 0) { return nil; } section = section / 3; ... } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { if (section % 3 != 2) { return nil; } section = section / 3; ... } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { int section = indexPath.section; section = section / 3; ... } 

改变你的TableView风格:

 self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

根据UITableView的苹果文档:

 UITableViewStylePlain- A plain table view. Any section headers or footers are displayed as inline separators and float when the table view is scrolled. UITableViewStyleGrouped- A table view whose sections present distinct groups of rows. The section headers and footers do not float. Hope this small change will help you .. 

@awulf答案的迅速版本,这很好!

 func scrollViewDidScroll(scrollView: UIScrollView) { let sectionHeight: CGFloat = 80 if scrollView.contentOffset.y <= sectionHeight { scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0) }else if scrollView.contentOffset.y >= sectionHeight { scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0) } } 

我已经了解到,只是设置tableHeaderView属性做到这一点,即:

  tableView.tableHeaderView = customView; 

就是这样。