UITableView不尊重heightForHeaderInSection / heightForFooterInSection?

时间:2009-09-06 21:50:48

标签: iphone cocoa-touch

我有一个UITableView,在某些情况下,某些部分的行数为零。我的目标是,如果这是真的,我不希望在表视图中浪费任何空间,它看起来应该没有数据。

我遇到的问题是这些部分的页眉和页脚,即使没有行也会显示,尽管我重写了委托方法以返回0.0f。

这就是它的样子 - 你可以看到顶部有~20p的灰色空间,页眉和页脚大约10p,每个部分有0行。

alt text
(来源:hanchorllc.com

这是我的伪代码:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
     if ([section hasRow]) {
          return 10.0f;
     } else {
          return 0.0f;
     }
}



- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
     if ([section hasRow]) {
          return 10.0f;
     } else {
          return 0.0f;
     }
}

我已经确认正在调用这些方法并且正在执行正确的执行路径。

一个皱纹 - 这个视图控制器正在使用XIB,而UITableView的剖面页眉和页脚值设置为10.0(默认值),但我认为如果实现了委托方法,它会被覆盖。

这是一款定位于3.0的应用。

我做错了什么?

9 个答案:

答案 0 :(得分:34)

这有点棘手,因为不接受0.0f值。但任何接近于零的东西都可以解决问题。如果您决定不是像素完美并且想要圆形数字,那么1.0f将几乎相同,因为1px的高度差异将是相当明显的。

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    if(section == 1 )
        return 0.000001f;
    else return 44.0f; // put 22 in case of plain one..
}

-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return 0.000001f; //removing section footers
}

答案 1 :(得分:25)

在iPhone上的“分组”UITableView中,它仍然会为页眉和页脚呈现最小高度,实际上会忽略您的代码以将其设置为零。它没有链接到XIB默认值。

这是因为零高度部分页眉或页脚看起来很奇怪。因此,Apple已经下令不能将标题高度设置为0.因此,根据您的屏幕截图,多个“空”部分会变得奇怪。

我担心这一切都是因为当没有数据行时,你会错误地清除标题大小;相反,你应该不要为空部分调用任何方法。这是一个糟糕的技术,因为基本上iPhone必须调用比它应该更多的方法,并且你渲染的标题比你想要的多(通常 - 有时人们想要留下那里的空白标题,例如用于拖放)

因此,举例来说,让我们假设您有多个部分,但只有部分部分具有多个部分(可能基于用户设置/过滤器)。

实施它的错误方式是:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return totalNumberOfPossibleSections;
}

然后对于每个部分,您没有结果:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  if (![section hasRow]) return 0;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
  if (![section hasRow]) return 0.0f;
}

正确实施方式是:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  return numberOfSectionsWhichHaveAtLeastOneRowInThem;
}

然后每个部分至少会有一个结果。这样,甚至没有渲染没有数据的部分,甚至没有为它们调用方法。 注意:我的两个变量名称用于表达它们包含的内容!它们不是特殊的Apple变量......

希望有所帮助!

答案 2 :(得分:9)

如果tableView:heightForHeaderInSection:不是tableView:viewForHeaderInSection:,或者nil不是tableView:titleForHeaderInSection:nil,则表格似乎尊重@""。对于页脚高度也是如此。

因此,假设您没有任何节标题视图或标题,只需将其添加到您的表委托:

- (UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
  return [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
}

答案 3 :(得分:3)

我遇到了类似的问题:  我从XIB(与您相同)加载UITableView,并为tableView:heightForFooterInSection(与您相同)的部分页脚提供了0高度,但忽略了该值。

修复很简单:在XIB中也将页脚高度设置为0.0。 (在Interface Builder中选择Table View,按Command-3查看Size Inspector,查找顶部附近的页脚高度字段)

一旦完成,它就按照预期服从自定义页脚高度。 (也许它将XIB页脚高度视为最小值?)

答案 4 :(得分:3)

我发现在我的情况下需要做两件事来杀死幻影页脚:

1)将表格视图sectionFooterHeight设置为0,即viewDidLoad添加:

tableView.sectionFooterHeight = 0

2)添加委托方法:

override func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
    return UIView(frame: CGRect.zero)
}

(使用Swift 2.2)

答案 5 :(得分:1)

它对我有用:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    tableView.sectionHeaderHeight = (section == 0 ? 10 : 0);
    return tableView.sectionHeaderHeight;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    tableView.sectionFooterHeight = (section == 0 ? 20 : 4);
    return tableView.sectionFooterHeight;
}

答案 6 :(得分:0)

实际上,与我相反,它正在以其他方式发生。我已经在xib中将节标题指定为10,但是对于第一节,我想要一个大小标题的标题。我在我的UITableViewCotroller

中使用此方法
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section==0)
        return 125;
    return tableView.rowHeight;
}

但是即使方法被调用,节标题高度也不会改变。

答案 7 :(得分:0)

我对这个问题的解决方案是关于h4xxr如何描述的,但是我有一个稍微不同的方法来构建动态数量的部分。

首先,我定义了一个方法,它将遍历我的数据结构并标记数据是否应该显示在表中。此标志存储在一个数组中,以便我可以包含尽可能少的部分或多个部分。如果我们只关注每个部分的单元格数量,我可以更好地描述这个实现:

假设我的第一部分是姓名,姓氏和年龄的联系方式。我将使用id为'1'定义此部分(虽然技术上我稍后会解释这可能是任何数字)。现在,如果我的方法确定此部分应该可见,我将值'1'推送到数组上。

我希望展示的下一部分是地址,可能有3-4行/单元格。如上所述,我的方法中的逻辑通过将数字“2”推到数组上来确定地址应该是否可见。

现在.. ..如果我们想要两个部分都可见,我们将有一个长度为2的数组和两个项目[1,2]。如果我们只希望联系人详细信息可见,那么我们的数组的长度为1,只有地址[1]和[2]。

现在我们可以返回数组的长度来定义我们想要的部分数量。

我们的switch语句现在看起来像这样:

switch(ourArray[indexPath.section]){
    case 1:
        <Return the number of rows for the contact details which we said would be 3>
        break;
    case 2:
        <Return the number of rows for the address details which we said would be 4>
        break;
    case 3:
        <Return another number for some section that is referenced by the id '3'>
        break; 
}

注意我已将案例3放入交换机中。因为我们示例中的数组只包含值'1'和'2',所以除非我们决定通过将它推入数组来添加/启用这种情况,否则情况3永远不会匹配并被忽略。

另请注意,我们可以在定义哪些部分可见的逻辑的方法中,通过在数组中的不同位置插入/推送它们来更改部分的顺序。

我虔诚地使用上述内容,因为它允许我解耦分段的索引和构造。

最后,在我使用'reloadData'更新我的表之前,我将调用我的方法,它将构造数组并提供正确的段ID的长度和顺序,以允许我的tableview知道如何构建自己。如果我的数据发生变化或以某种方式进行过滤,我将再次调用此方法并重新构建数组。

答案 8 :(得分:0)

我使用以下解决方案:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return section == 0 ? CGFloat.leastNormalMagnitude : 8
}

func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
    return 0
}

结果:

result