152

我有一个包含两个部分的 UITableView。这是一个简单的表格视图。我正在使用 viewForHeaderInSection 为这些标题创建自定义视图。到目前为止,一切都很好。

默认滚动行为是,当遇到一个部分时,部分标题保持锚定在导航栏下方,直到下一个部分滚动到视图中。

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

我错过了一些明显的东西吗?

谢谢。

4

19 回答 19

175

我解决这个问题的方法是contentOffset根据(扩展)contentInset中的调整如下:UITableViewControllerDelegateUIScrollViewDelegate

- (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 节标题高度匹配,则手指感觉似乎是完美或接近完美。}

于 2010-10-21T05:36:49.160 回答
86

您还可以在顶部添加一个零行的部分,只需将上一部分的页脚用作下一部分的页眉。

于 2011-02-26T15:14:03.477 回答
36

如果是我这样做,我会利用 Plain 样式的 UITableViews 具有粘性标题而 Grouped 样式的 UITableViews 没有这一事实。我可能至少会尝试使用自定义表格单元格来模仿分组表格中普通单元格的外观。

我实际上还没有尝试过,所以它可能不起作用,但这就是我建议做的。

于 2009-12-20T08:54:04.330 回答
28

我知道它来晚了,但我找到了最终的解决方案!

您想要做的是,如果您有 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

于 2011-12-02T00:28:47.500 回答
16

最初发布在这里,使用 IB 的快速解决方案。虽然很简单,但同样可以通过编程方式完成。

实现此目的的一种可能更简单的方法(使用 IB):

将 UIView 拖到 TableView 上以使其成为标题视图。

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

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

于 2013-01-30T17:12:02.373 回答
15

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

  1. 将表格视图样式设置为UITableViewStyleGrouped
  2. 将表格视图设置backgroundColor[UIColor clearColor]
  3. backgroundView每个表视图单元格上的设置为空视图backgroundColor [UIColor clearColor]
  4. 如有必要,适当设置表格视图rowHeight,或者tableView:heightForRowAtIndexPath:在各个行具有不同高度时覆盖。
于 2011-08-01T16:13:47.353 回答
15

到目前为止,我对这里描述的解决方案并不满意,所以我尝试将它们结合起来。结果是以下代码,灵感来自@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)]];
于 2013-02-28T18:50:28.887 回答
15

只需更改 TableView 样式:

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

UITableViewStyle 文档

UITableViewStylePlain - 一个普通的表格视图。滚动表格视图时,任何部分的页眉或页脚都显示为内联分隔符并浮动。

UITableViewStyleGrouped - 一个表格视图,其部分呈现不同的行组。部分页眉和页脚不浮动。

于 2015-07-14T21:36:00.883 回答
11

选择分组的 TableView 样式

从情节提要中的 tableView 的 Attribute Inspector 中选择 Grouped Table View 样式。

于 2017-04-04T04:35:09.963 回答
5

将表格的 headerView 设置为与剖面视图中的标题相同高度的透明视图。还要在 -height 处使用 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];
于 2011-08-11T14:37:09.363 回答
5

更改您的 TableView 样式:

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

根据 UITableView 的苹果文档:

UITableViewStylePlain - 一个普通的表格视图。滚动表格视图时,任何部分的页眉或页脚都显示为内联分隔符并浮动。

UITableViewStyleGrouped - 一个表格视图,其部分呈现不同的行组。部分页眉和页脚不浮动。希望这个小小的改变能帮助你..

于 2016-05-08T02:30:39.357 回答
4

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

于 2012-10-19T16:46:08.053 回答
2

现在,分组样式看起来与 iOS 7 中的普通样式基本相同(在平整度和背景方面),对我们来说,最好和最简单(即最少 hacky)的解决方法是简单地将表格视图的样式更改为分组。当我们在顶部集成滚动导航栏时,使用 contentInsets 一直是个问题。使用分组表视图样式,它看起来完全一样(与我们的单元格),并且节标题保持固定。没有滚动怪异。

于 2014-04-09T00:40:48.490 回答
1

为您的 tableView 分配一个负插图。如果您有 22px 高的部分标题,并且您不希望它们变得粘稠,请在 reloadData 添加后立即添加:

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

对我来说就像一个魅力。也适用于部分页脚,只需在底部分配负插图。

于 2010-10-08T22:22:32.797 回答
0

在这里检查我的答案。这是在没有任何技巧的情况下实现非浮动节标题的最简单方法。

于 2012-12-06T01:23:30.273 回答
0

我将表格添加到滚动视图中,这似乎运作良好。

于 2010-05-10T00:11:43.223 回答
0

@LocoMike 的答案最适合我的 tableView,但是在使用页脚时它也坏了。因此,这是使用页眉和页脚时的更正解决方案:

- (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;
    ...
}
于 2013-04-21T16:39:01.467 回答
0

@awulf 答案的 Swift 版本,效果很好!

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)
    }
}
于 2016-09-07T16:50:15.620 回答
-2

我了解到,只需设置 tableHeaderView 属性就可以了,即:

 tableView.tableHeaderView = customView;

就是这样。

于 2012-01-23T12:19:34.693 回答