我有两个部分的UITableView。这是一个简单的表格视图。我正在使用viewForHeaderInSection为这些标题创建自定义视图。到目前为止,一切都很好。
默认的滚动行为是,遇到某个节时,该节标题保持锚定在导航栏下方,直到下一个节滚动到视图中为止。
我的问题是:我可以更改默认行为,以使节标题不停留在顶部,而是在导航栏下滚动浏览节的其余部分吗?
我缺少明显的东西吗?
谢谢。
我有两个部分的UITableView。这是一个简单的表格视图。我正在使用viewForHeaderInSection为这些标题创建自定义视图。到目前为止,一切都很好。
默认的滚动行为是,遇到某个节时,该节标题保持锚定在导航栏下方,直到下一个节滚动到视图中为止。
我的问题是:我可以更改默认行为,以使节标题不停留在顶部,而是在导航栏下滚动浏览节的其余部分吗?
我缺少明显的东西吗?
谢谢。
Answers:
我解决此问题的方法是contentOffset
根据(extends )contentInset
中的来调整,如下所示:UITableViewControllerDelegate
UIScrollViewDelegate
- (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部分标题高度匹配,则手指感觉似乎是完美的或接近完美。}
您还可以在顶部添加一个零行的节,只需将上一节的页脚用作下一节的页眉即可。
如果是我这样做,我将利用一个事实,即Plain风格的UITableViews具有粘性标头,而Grouped风格的UITableViews没有标头。我可能至少会尝试使用自定义表格单元格来模拟分组表格中普通单元格的外观。
我实际上没有尝试过,因此可能无法正常工作,但这就是我建议的做法。
tableView.separatorColor = [UIColor clearColor];
模仿纯表格视图。
我知道来晚了,但是我找到了最终的解决方案!
您要执行的操作是,如果有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
UITableView
我使用的高度定制化的情况下,它不能很好地工作。
要以非骇客的方式解决此问题,需要完成几件事:
UITableViewStyleGrouped
backgroundColor
为[UIColor clearColor]
backgroundView
每个表格视图单元格上的设置为空视图backgroundColor [UIColor clearColor]
rowHeight
适当地设置表格视图,tableView:heightForRowAtIndexPath:
如果各个行的高度不同,则将其覆盖。UITableViewStyleGrouped
由于表格单元格的多余边距会改变其与标题的对齐方式。当您实际上想要描绘一个多列表并使用标题显示列标题(然后使各个表条目与这些标题对齐)时,这是一个问题。
最初发布在这里,是使用IB的快速解决方案。尽管可以很简单地通过编程来完成。
实现这一目标的一种可能更简单的方法(使用IB):
将UIView拖到TableView上以使其成为标题视图。
- 将标题视图高度设置为100px
- 将tableview contentInset(顶部)设置为-100
- 现在,节标题将像任何常规单元格一样滚动。
有人评论说此解决方案隐藏了第一个标头,但是我没有注意到任何此类问题。它对我来说非常有效,并且是迄今为止我所见过的最简单的解决方案。
到目前为止,我对此处介绍的解决方案不满意,因此我尝试将它们结合起来。结果是以下代码,其灵感来自@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];
UITableViewStylePlain-纯表格视图。滚动表格视图时,所有节的页眉或页脚都将显示为行内分隔符并浮动。
UITableViewStyleGrouped-一个表视图,其部分显示不同的行组。节的页眉和页脚不浮动。
使用透明视图设置表的headerView,并在剖面视图中设置标题的高度。还要使用-height框架初始化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];
我找到了一个替代解决方案,使用每个节的第一个单元格代替真实的标题节,该解决方案看起来不太干净,但效果很好,可以为标题节使用已定义的原型单元格,并在cellForRowAtIndexPath方法中要求indexPath.row == 0,如果为true,则使用标头节原型单元格,否则使用默认原型单元格。
indexPath.row
&indexPath.section
,请确保返回高度为0.0f
for,- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
以便标题不可见。
为您的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,但是在使用页脚时也坏了。因此,这是使用页眉和页脚时的更正解决方案:
- (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;
...
}
@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)
}
}