51

嗨,我想UITableHeaderFooterView在我的应用程序中使用,我正在这样做:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    [_tableView registerClass:[M3CTableViewCell class] forCellReuseIdentifier:@"cell"];
    [_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:@"footer"];

}

- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section {
    M3CHeaderFooter * footer = [[M3CHeaderFooter alloc]initWithReuseIdentifier:@"footer"];
    footer.textLabel.text = @"Test";
    return footer;
}

通过这样做,我在页脚的地方没有得到任何东西。而且这个方法甚至没有被调用,但我认为这个方法是UITableViewDelegate协议的一部分。

4

9 回答 9

70

使用可重用页眉/页脚视图的新 iOS 6 功能涉及两个步骤。你似乎只做了第一步。

第一步:您通过注册 UITableViewHeaderFooterView 的自定义子类(我假设您的 M3CHeaderFooter 是 UITableViewHeaderFooterView 的子类)来告诉表格视图要为节标题视图使用什么类。

第二步:通过实现 tableView 委托方法,告诉表视图对标题部分使用(和重用)什么视图

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

所以在你的 viewDidLoad 你会实现这样的东西:

    // ****** Do Step One ******
    [_tableView registerClass:[M3CHeaderFooter class] forHeaderFooterViewReuseIdentifier:@"TableViewSectionHeaderViewIdentifier"];

然后,您将在创建和显示表视图的类中实现表视图委托方法:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerReuseIdentifier = @"TableViewSectionHeaderViewIdentifier";

    // ****** Do Step Two *********
    M3CHeaderFooter *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
   // Display specific header title
   sectionHeaderView.textLabel.text = @"specific title";   

    return sectionHeaderView;    
}

现在请注意,您不需要子类 UITableViewHeaderFooterView 来使用它。在 iOS 6 之前,如果你想要一个部分的标题视图,你需要实现上面的 tableView 委托方法并告诉表视图每个部分使用什么视图。因此,每个部分都有您提供的 UIView 的不同实例。这意味着如果您的 tableView 有 100 个部分,并且在委托方法中您创建了一个 UIView 的新实例,那么您将为显示的 100 个部分标题为 tableView 提供 100 个 UIView。

使用可重用页眉/页脚视图的新功能,您可以创建 UITableViewHeaderFooterView 的实例,系统会为每个显示的节标题重用它。

如果您想拥有一个可重用的 UITableViewHeaderFooterView 而无需子类化,那么您只需将 viewDidLoad 更改为:

// Register the class for a header view reuse.
[_buttomTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"TableViewSectionHeaderViewIdentifier"];

然后你的委托方法:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *headerReuseIdentifier = @"TableViewSectionHeaderViewIdentifier";

   // Reuse the instance that was created in viewDidLoad, or make a new one if not enough.
    UITableViewHeaderFooterView *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
    sectionHeaderView.textLabel.text = @"Non subclassed header";

    return sectionHeaderView;

}

我希望这已经足够清楚了。

编辑: 子类化标题视图时,如果您希望向 headerView 添加自定义视图,则可以实现类似于以下的代码:

        // Add any optional custom views of your own
    UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 50.0, 30.0)];
    [customView setBackgroundColor:[UIColor blueColor]];

    [sectionHeaderView.contentView addSubview:customView];

在子类中执行此操作,而不是 viewForHeaderInSection: 委托方法(如下面的 Matthias 所述),将确保仅创建任何子视图的一个实例。然后,您可以在子类中添加任何允许您访问自定义子视图的属性。

于 2012-12-10T04:07:24.710 回答
9

UITableViewHeaderFooterView 是少数几个我会以编程方式处理视图而不是使用 Storyboard 或 XIB 的地方之一。由于您不能正式使用外观代理,并且没有 IB 方法可以在不滥用 UITableViewCells 的情况下做到这一点。我用老式的方式来做,只使用标签上的标签来获取自定义元素。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
    if (headerView == nil) {
        [tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:kSectionHeaderReuseIdentifier];
        headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kSectionHeaderReuseIdentifier];
    }

    UILabel *titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
    if (titleLabel == nil) {
        UIColor *backgroundColor = [UIColor blackColor];
        headerView.contentView.backgroundColor = backgroundColor;
        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10.0f, 0.0f, 300.0f, 44.0f)];
        titleLabel.textColor = [UIColor whiteColor];
        titleLabel.backgroundColor = backgroundColor;
        titleLabel.shadowOffset = CGSizeMake(0.0f, 0.0f);
        titleLabel.tag = 1;
        titleLabel.font = [UIFont systemFontOfSize:24.0f];
        [headerView.contentView addSubview:titleLabel];
    }

    NSString *sectionTitle = [self.sections objectAtIndex:section];
    if (sectionTitle == nil) {
        sectionTitle = @"Missing Title";
    }

    titleLabel.text = sectionTitle;

    return headerView;
}
于 2013-08-05T20:49:48.093 回答
7

这是一篇旧帖子并且有很好的答案,但我想分享另一个解决我遇到的非常相似的问题的方法。

起初,我使用:

-(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

使用我的标题视图的自定义原型单元格。这样子类化 UITableViewCell

    static NSString *cellIdentifier = @"CustomHeaderCell";
CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

但是,当为节标题上方的 TableView 单元格设置动画时(使它们高一倍),标题视图会消失。正如所指出的,这是因为实现只提供了一个视图,而不是一个可重用的视图。

我没有放弃自定义原型单元格的所有内容,而是实现了 UITableViewHeaderFooterWithIdentifier 并将其设置为原型单元格的 contentView,而没有继承 UITableViewHeaderFooterWithIdentifier。

  static NSString *customHeaderViewIdentifier = @"CustomHeaderView";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];

headerView = (UITableViewHeaderFooterView *)cell.contentView;

我意识到这会创建标题视图的两个实例(至少我认为它会......)但是它确实允许您保留自定义原型单元的好处,而无需以编程方式进行所有操作。

完整代码:

  // viewDidLoad
    [myTableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"CustomHeaderView"];

// Implement your custom header
 -(UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
     static NSString *cellIdentifier = @"CustomHeaderCell";
    CustomHeaderCell * cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    static NSString *customHeaderViewIdentifier = @"CustomHeaderView";
    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:customHeaderViewIdentifier];

// do your cell-specific code here
// eg. cell.myCustomLabel.text = @"my custom text"

    headerView = (UITableViewHeaderFooterView *)cell.contentView;

return headerView;
}
于 2015-02-18T14:46:59.050 回答
5

有几种方法可以解决这个问题,但这是Swift中的一种解决方案:这里的想法是我们有一个UITableViewHeaderFooterView被调用的子类SNStockPickerTableHeaderView;它公开了一个名为的方法,configureTextLabel()该方法在调用时设置文本标签的字体和颜色。我们仅在设置标题后调用此方法,即 from, willDisplayHeaderView,并且字体设置正确。

标题视图还支持自定义行分隔符,以将其与其他单元格区分开来。

// MARK: UITableViewDelegate

func tableView(tableView:UITableView, willDisplayHeaderView view:UIView, forSection section:Int) {
  if let headerView:SNStockPickerTableHeaderView = view as? SNStockPickerTableHeaderView {
    headerView.configureTextLabel()
  }
}

func tableView(tableView:UITableView, viewForHeaderInSection section:Int) -> UIView? {
  var headerView:SNStockPickerTableHeaderView? = tableView.dequeueReusableHeaderFooterViewWithIdentifier(kSNStockPickerTableHeaderViewReuseIdentifier) as? SNStockPickerTableHeaderView
  if (headerView == nil) {
    // Here we get to customize the section, pass in background color, text 
    // color, line separator color, etc. 
    headerView = SNStockPickerTableHeaderView(backgroundColor:backgroundColor,
      textColor:primaryTextColor,
      lineSeparatorColor:primaryTextColor)
  }
  return headerView!
}

这是习俗UITableViewHeaderFooterView

import Foundation
import UIKit

private let kSNStockPickerTableHeaderViewLineSeparatorHeight:CGFloat = 0.5
private let kSNStockPickerTableHeaderViewTitleFont = UIFont(name:"HelveticaNeue-Light", size:12)

let kSNStockPickerTableHeaderViewReuseIdentifier:String = "stock_picker_table_view_header_reuse_identifier"

class SNStockPickerTableHeaderView: UITableViewHeaderFooterView {

  private var lineSeparatorView:UIView?
  private var textColor:UIColor?

  required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }

  // We must implement this, since the designated init of the parent class
  // calls this by default!
  override init(frame:CGRect) {
    super.init(frame:frame)
  }

  init(backgroundColor:UIColor, textColor:UIColor, lineSeparatorColor:UIColor) {
    super.init(reuseIdentifier:kSNStockPickerTableHeaderViewReuseIdentifier)
    contentView.backgroundColor = backgroundColor
    self.textColor = textColor
    addLineSeparator(textColor)
  }

  // MARK: Layout

  override func layoutSubviews() {
    super.layoutSubviews()
    let lineSeparatorViewY = CGRectGetHeight(self.bounds) - kSNStockPickerTableHeaderViewLineSeparatorHeight
    lineSeparatorView!.frame = CGRectMake(0,
      lineSeparatorViewY,
      CGRectGetWidth(self.bounds),
      kSNStockPickerTableHeaderViewLineSeparatorHeight)
  }

  // MARK: Public API

  func configureTextLabel() {
    textLabel.textColor = textColor
    textLabel.font = kSNStockPickerTableHeaderViewTitleFont
  }

  // MARK: Private

  func addLineSeparator(lineSeparatorColor:UIColor) {
    lineSeparatorView = UIView(frame:CGRectZero)
    lineSeparatorView!.backgroundColor = lineSeparatorColor
    contentView.addSubview(lineSeparatorView!)
  }
}

这是结果,请参阅“热门股票”部分的标题:

                              在此处输入图像描述

于 2015-05-10T22:10:27.557 回答
3

我无法在Cameron Lowell Palmer 的帖子下发表评论,但要回答 Christopher King,有一种简单的方法可以确保在不对 UITableViewHeaderFooterView 进行子类化的情况下重复使用,但仍使用自定义子视图。

首先,不要为标题视图重用注册该类。

然后在 tableView:viewForHeaderInSection: 你只需要在需要时创建 UITableViewHeaderFooterView :

-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    static NSString *kYourTableViewReusableHeaderIdentifier = @"ID";

    UILabel *titleLabel = nil;

    UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:kYourTableViewReusableHeaderIdentifier];

    if (headerView == nil) {

        headerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:kYourTableViewReusableHeaderIdentifier];

        titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(...)];
        titleLabel.tag = 1;
        // ... setup titleLabel 

        [headerView.contentView addSubview:titleLabel];
    } else {
        // headerView is REUSED
        titleLabel = (UILabel *)[headerView.contentView viewWithTag:1];
    }

    NSString *sectionTitle = (...); // Fetch value for current section
    if (sectionTitle == nil) {
        sectionTitle = @"Missing Title";
    }

    titleLabel.text = sectionTitle;

    return headerView;
}
于 2014-07-16T01:34:12.943 回答
1

这是一种“快速而肮脏”的方式来实现这一目标。它将在标题中制作一个小的蓝色标签。我已经确认这在 iOS 6 和 iOS 7 中可以正常工作。

在你的 UITableViewDelegate 中:

 -(void)viewDidLoad
{
...
    [self.table registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"Header"];
...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 34.;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UITableViewHeaderFooterView *header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"Header"];

    UILabel *leftlabel = [[UILabel alloc] initWithFrame:CGRectMake(0., 0., 400., 34.)];
    [leftlabel setBackgroundColor:[UIColor blueColor]];

    [header.contentView addSubview:leftlabel];
    return header;
}
于 2013-10-04T19:01:00.473 回答
0

万一它在上面的彻底答案中迷失了,人们可能遗漏的事情(与标准cellForRowAtIndexPath:方法相比)是您必须注册用于节标题的类。

[tableView registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:@"SectionHeader"];

尝试添加registerClass:forHeaderFooterViewReuseIdentifier:,看看它是否开始工作。

于 2016-02-22T19:50:26.293 回答
0

该方法可能未被调用的原因之一是表格的样式。标准与分组处理页眉/页脚的方式不同。这可以解释为什么它没有被调用。

于 2017-02-08T17:08:31.480 回答
-1
  1. 设置实例的delegate属性UITableView以引用实现下一个方法的控制器:

  2. 返回节页脚视图的方法:

    要求委托将视图对象显示在表视图的指定部分的页脚中。 - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section

  3. 部分页脚中的视图高度:

    向代理询问用于特定部分页脚的高度。

    - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger) 部分

于 2012-10-15T17:09:50.920 回答