在InterfaceBuilder中的UITableViewHeaderFooterView

43

我想使用IB创建一个自定义的表头部分视图,并将其放在一个单独的.xib文件中。

然而,在IB中我找不到一个名为UITableViewHeaderFooterView(类似于UITableViewCell)的组件,并为其分配重用。

那么如何创建自定义的表头部分呢?

我创建了一个名为MySection的类,它继承自UITableViewHeaderFooterView。同时,我创建了一个.xib文件MySection.xib,并为其注册了可供单元格重用的xib。

但问题是,如何使用initWitReuseIdentifier....方法呢?

9个回答

70

完全是可能的,而且苹果提供了一个例子这里

下载示例代码并查看SectionHeaderView.xib。

方法是创建一个只有一个UIView的xib,然后将类类型设置为继承自UITableViewHeaderFooterView的类。

一旦你有了一个从UITableViewHeaderFooterView继承的类的nib,就可以调用以下内容注册该类以在表头或表尾中重复使用:

static NSString * const SectionHeaderViewIdentifier = @"SectionHeaderViewIdentifier";

[self.tableView registerNib:[UINib nibWithNibName:@"SectionHeaderView" bundle:nil] forHeaderFooterViewReuseIdentifier:SectionHeaderViewIdentifier];

为了将视图投入使用,实现表格委托方法tableView:viewForHeaderInSection:如下:

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSinteger)section {

    SectionHeaderViewClass *sectionHeaderView = (SectionHeaderView *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderViewIdentifier];

    // Do stuff...

    return sectionHeaderView;
}

26
在iOS8中会出现这样的警告:设置UITableViewHeaderFooterView的背景颜色已被弃用。 请改用contentView.backgroundColor。为了修复,可以在IB中将UIView的背景颜色设置为“默认”。 - Farhad Malekpour
3
在 iOS 8.3 中,您还需要设置 UITableView 的 sectionHeaderHeight 属性,否则它将默认为 0,导致您的委托方法不会被调用。(是的,这很蠢。) - patr1ck
1
澄清OP(因为我花了一段时间):您的XIB应该有一个根级子视图(类似于UITableViewCell的内容视图),而所有其他视图都应该是其子视图。此外,除了@patr1ck上面的评论之外,在iOS 10.x中,您必须设置tableView.sectionHeaderHeighttableView.estimatedSectionHeaderHeight两者(即使您在UITableViewDelegate中覆盖了各个部分的值)。 - Robert Atkins
4
问题在于,你的表头/表尾视图的子视图不会成为内容视图的子视图,它们应该是内容视图的子视图,但实际上它们直接被添加到UITableViewHeaderFooterView中。 - smileyborg
6
在Interface Builder中是否有一种方法可以将子视图添加到UITableViewHeaderFooterViewcontentView中? - Apoorv Khatreja

21

我已经写了一个指南(在iOS 9上测试过),它包括4个步骤:

  1. 子类化UITableViewHeaderFooterView
  2. 使用子类视图创建 Nib,并添加一个包含所有其他头部/尾部视图的容器视图
  3. viewDidLoad中,为表格视图调用registerNib:forHeaderFooterViewReuseIdentifier:
  4. 实现viewForHeaderInSection并使用dequeueReusableHeaderFooterViewWithIdentifier获取头部/尾部视图

1
我不知道为什么在Interface Builder中使用Views时它不能正常工作。它没有在视图上实例化我的UILabel。我尝试将其嵌套在容器视图中。它们都包含在自定义的UITableViewHeaderFooterView子类中。 - Andrew Kirna
如何在UITableViewHeaderFooterView中添加按钮动作? - Ramakrishna
@AndrewKirna 页脚视图上的内容不可见或无法加载。只显示空的灰色条,甚至背景颜色也没有改变。不知道出了什么问题。 - iPhone 7
嗨,@iPhone7。我决定回应你,因为我仍然在使用iPhone 7......开个玩笑,但那就是我的手机,我之前评论的原因是我也没有让它工作起来。自那时以来,我一直在使用Swift设计我的所有自定义UITableViewHeaderFooterView。然后,我将这些类注册到表格中,并使用dequeueReusableHeaderFooterView(withIdentifier:)应用它们。希望这能帮到你! - Andrew Kirna

5
虽然这些答案都有效,但它们并没有完全解决原始问题——如何使用Interface Builder设置reuseIdentifier。确实可以通过“用户定义的运行时属性”来实现。您可以使用属性直接在Interface Builder中设置reuseIdentifier

Interface Builder user-defined runtime attributes

这样做将完成与UITableViewCell界面构建器属性检查器中本机reuseIdentifier字段完全相同的事情。

似乎是一个错误,因为从技术上讲,在“Table View”中可以取消排队“Header View”,所以应该有一个添加标识符的字段。 - Alizain Prasla

3
以下方法可让我将IB项目作为变量进行拖动分配。UITableViewHeaderFooterView没有默认支持此功能。
  1. 创建一个(New File/CocoaTouchClass)UITableViewHeaderFooterView.h.m.xib文件。
  2. 暂时将父类从UITableViewHeaderFooterView更名为UIView。按需将UI项目拖放到代码中,IB会正确分配键值对。完成后恢复为UITableViewHeaderFooterView。
  3. 在您的tableview中,使用registerNib:注册而不是registerClass:。其余tableview准备工作照常(例如:dequeue)。

1
自iOS 8以来,UITableHeaderFooterView的子视图应该在容器视图中,并且不应在header/footer视图上设置背景。Object Library缺少UITableHeaderFooterView,因此我尝试了在xib中创建一个UIView并将另一个UIView添加到其中作为Container View的方法。我的担忧是UITableHeaderFooterView上没有content view outlet,我无法确定我的content view实际上是否最终成为content view。
这听起来像是一种hack或API误用,然而我使用这种方法没有遇到任何警告或问题:
1. 创建UITableHeaderFooterView的子类 2. 创建一个空的xib 3. 从对象库中拖动一个UITableViewCell 4. 将你的UITableHeaderFooterView的类分配给该单元格 5. 分配重用标识符
请评论此方法是否存在任何(潜在的)问题。

3
我无法将UITableHeaderFooterView类指定给单元格,Xcode不接受。 - Ortwin Gentz

0
只需在IB中创建视图并分配其类即可(无需像自定义UITableViewCell一样在界面构建器中设置重用标识符)。

-1

UITableViewHeaderFooterView文档包含registerNib:forHeaderFooterViewReuseIdentifier:方法

但是目前(截至2013年9月4日),Interface Builder中的对象库不包括UITableViewHeaderFooterView。 这使得registerNib:forHeaderFooterViewReuseIdentifier:无用,因为没有办法在nib中正确配置视图。 也许最好尝试重用单元格...


-1
  1. 在xib中创建新视图

  2. 从nib中加载视图并将其设置为tableview的footerview

UIView *headerview = [[[NSBundle mainBundle] loadNibNamed:@"ReguistrationHeaderView" owner:self options:nil] firstObject]; [self.tableview setTableFooterView:headerview];


-2

我通常使用UITableViewCell作为表格的头部(或尾部),以便能够直接在Storyboard中编辑它们。

我的工作流程:

  • 我创建一个名为MyHeaderTableViewCell的类,该类继承UITableViewCell并添加所有所需的输出
  • 我在Storyboard中的表格中添加一个UITableViewCell
  • 我给它一个重用标识符(例如:“HeaderCell”)
  • 我出列单元格并使用其内容作为我的标题

关键部分是返回headerCell的contentView(而不是headerCell本身),否则当使用reloadRowsAt或类似函数时会遇到奇怪的行为(最多是标题消失)。

这是我的代码:

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

    let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! MyHeaderTableViewCell

    headerCell.lblTitle.text = "My Title"

    return headerCell.contentView }

我从来没有在这方面遇到过问题(或者至少我的客户总是付款给我)。


你写道你从未遇到任何问题,但是这似乎是一种冒险的方法和滥用API。 - Peter Lapisu
1
@PeterLapisu,感谢您的回复。我同意您的观点,这可能存在风险,而且滥用API也是不好的,但只要它能够正常运行且没有任何大的缺陷,我认为这是在清晰代码和易用性之间做出的一个很好的权衡。所以这只是一种解决方案,虽然我同意您的看法,它并不是最干净的解决方案。 - Il Pisanello
到现在已经5年了,我的方法一直没有问题。 - Il Pisanello

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接