如何使用UITableViewHeaderFooterView?

时间:2012-10-15 17:00:50

标签: ios objective-c uitableview

您好我想在我的应用中使用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;
}

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

9 个答案:

答案 0 :(得分:69)

使用可重复使用的页眉/页脚视图的新iOS 6功能包含两个步骤。你好像只是迈出了第一步。

第一步:通过注册UITableViewHeaderFooterView的自定义子类(我假设您的M3CHeaderFooter是UITableViewHeaderFooterView的子类),告诉表查看用于节头视图的类。

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

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

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

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

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

- (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个部分,并且在delegate方法中你创建了一个UIView的新实例,那么你就可以为显示的100个部分标题提供tableView 100 UIViews。

使用可重复使用的页眉/页脚视图的新功能,您可以创建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:delegate方法(如Matthias所述),将确保只创建任何子视图的一个实例。然后,您可以在子类中添加任何属性,以允许您访问自定义子视图。

答案 1 :(得分:9)

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

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

答案 2 :(得分:7)

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

起初,我用过:

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

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

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

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

我没有使用自定义原型单元格放弃所有内容,而是实现了UITableViewHeaderFooterWithIdentifier并将其设置为prototyped单元格的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;
}

答案 3 :(得分:5)

有几种方法可以解决这个问题,但这里有一个 Swift 的解决方案:这里的想法是我们有UITableViewHeaderFooterView的子类叫SNStockPickerTableHeaderView;它公开了一个名为configureTextLabel()的方法,在调用时,它设置文本标签的字体和颜色。我们只在设置了标题后调用此方法,即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!)
  }
}

结果如下,请参阅“热门股票”部分标题:

enter image description here

答案 4 :(得分:3)

我无法在Cameron Lowell Palmer post下发表评论但是为了回答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;
}

答案 5 :(得分: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;
}

答案 6 :(得分:0)

如果它在上面的完整答案中丢失,那么人们可能遗漏的东西(与标准的cellForRowAtIndexPath:方法相比)是你必须注册用于节标题的类。

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

尝试添加registerClass:forHeaderFooterViewReuseIdentifier:并查看它是否开始有效。

答案 7 :(得分:0)

可能无法调用方法的原因之一是表的样式。 Standard vs Grouped以不同方式处理页眉/页脚。这可以解释为什么它没有被调用。

答案 8 :(得分:-1)

  1. 设置delegate实例的UITableView属性以引用实现下一个方法的控制器:

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

      

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

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

      

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

         

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