UITableView不尊重heightForHeaderInSection / heightForFooterInSection?

问题描述 投票:22回答:9

我有一个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的应用。

我究竟做错了什么?

iphone cocoa-touch
9个回答
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变量......

希望有所帮助!


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
}

9
投票

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

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

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

3
投票

我有一个类似的问题:我从XIB(与你相同)加载UITableView,并为tableView:heightForFooterInSection(与你相同)的某些部分页脚提供0高度,但该值被忽略。

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

完成后,它遵循预期的自定义页脚高度。 (也许它将XIB页脚高度视为最小值?)


3
投票

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

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)


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;
}

0
投票

实际上,对我来说,它正在发生反过来。我已经在xib中将节标题指定为10,但是对于第一节,我想要一个大小标题的标题。我在我的UITableViewCotroller中使用此方法

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section==0)
        return 125;
    return tableView.rowHeight;
}

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


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知道如何构建自己。如果我的数据发生变化或以某种方式过滤,我将再次调用此方法并重建数组。


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

© www.soinside.com 2019 - 2024. All rights reserved.