在TableView中构建页眉和页脚


问题


要在一个TableView中创建一个页眉或页脚。

方案


创建一个视图(可以是一个标签,图片等,任何可以直接或者间接的视图子类),然后把这个视图分配到TableView的1个Section的页眉或页脚中。也可以指定某个页眉或页脚的高度。

讨论


TableView可以有多个页眉页脚。一个TableView的每个Section都可有它自己的页眉和页脚,如果在一个TableView中有3个Section,你就最多有3个页眉和3个页脚。你不必给这些Section的每个部分提供页眉页脚。告诉TableView是否在一个Section要页眉或页脚,通过其委托你是否把这些视图传递到TableView中,你想在TableView中为Section(多个)提供页眉(多的)、页脚(多个),这些都取决于你。TableView中的页眉页脚成了TableView的一部分,这就意味着当TableView的内容滚动时,TableView中的页眉页脚也同样会滚动。

TableView-7

图4-7. TableView中页眉和页脚

通过UITableViewDataSource定义的方法可以确定一个Section内页眉和页脚的高度。

通过UITableViewDelegate协议中定义的方法可以确定为一个表视图中一个Section的页眉、页脚展示的实际视图。

创建一个带有一个TableView的简单APP。随后提供2个标签,他们属于UILabel类,一个做页眉,另一个做页脚。仅用3个cell填充这个TableView。在页眉中放入文字”Section 1 Header”。在页脚标签上放入文字”Section 1 Footer”,以根视图控制器的头文件开始,我们定义一个TableView。

#import <UIKit/UIKit.h>

@interface TableViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *myTableView;
@end

创建一个分组的表视图,并给它加载三个单元格。

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
	UITableViewCell *result = nil;
	static NSString *CellIdentifier = @"CellIdentifier";
	result = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

	if (result == nil) {
		result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
	}

	result.textLabel.text = [[NSString alloc] initWithFormat:@"Cell %ld",
	(long)indexPath.row];

	return result;
}

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return 3;
}

- (void)viewDidLoad {
	[super viewDidLoad];
	self.myTableView =
	[[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
	self.myTableView.dataSource = self;
	self.myTableView.delegate = self;
	self.myTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	[self.view addSubview:self.myTableView];
}

- (BOOL)shouldAutorotateToInterfaceOrientation :(UIInterfaceOrientation)interfaceOrientation {
	return YES;
}

这个部分令人振奋。现在可以使用UITableViewDelegate定义的2个重要方法来提供一个页眉标签和另一个页脚标签。这两个方法分别是:

  • tableView:viewForHeaderInSection:

此方法返回一个UIView类型的值。此方法返回的视图将显示为viewForHeaderInSection参数指定部分的页眉。

  • tableView:viewForFooterInSection:

此方法返回一个UIView类型的值。此方法返回的视图将显示为viewForFooterInSection参数指定部分的页脚。

实现方法,并从其中返回一个UILabel的实例。按照计划,在页眉标签放入”Section 1 Header”,在页脚标签放入文字”Section 1 Footer”。

- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
	UILabel *result = nil;

	if ([tableView isEqual:self.myTableView]) {
		result = [[UILabel alloc] initWithFrame:CGRectZero];
		result.text = @"Section 1 Header";
		result.backgroundColor = [UIColor clearColor];
		[result sizeToFit];
	}

	return result;
}

- (UIView *) tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
	UILabel *result = nil;

	if ([tableView isEqual:self.myTableView]) {
		result = [[UILabel alloc] initWithFrame:CGRectZero];
		result.text = @"Section 1 Footer";
		result.backgroundColor = [UIColor clearColor];
		[result sizeToFit];
	}

	return result;
}

如果你现在在iPhone模拟器上运行你的APP,你肯定会看到一些奇怪的事件。如图4-8所示:

IOS 7 viewForHeaderInSection 的section从1开始而不是从0开始

TableView-8

图4-8. TableView中的页眉和页脚没有正确对齐

The reason for this misalignment of the labels is because the table view doesn’t really know the height of these views. To specify the height of the header and footer views, we need to use the following two methods which are defined in the UITableViewDele gate protocol:

  • tableView:heightForHeaderInSection:

The return value of this method is of type CGFloat, and it specifies the height of the header for a section in a table view. The section’s index is passed through the heightForHeaderInSection parameter.

  • tableView:heightForFooterInSection:

The return value of this method is of type CGFloat, and it specifies the height of the footer for a section in a table view. The section’s index is passed through the heightForHeaderInSection parameter.

- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
	CGFloat result = 0.0f;

	if ([tableView isEqual:self.myTableView] && section == 0) {
		result = 30.0f;
	}

	return result;
}

- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
	CGFloat result = 0.0f;

	if ([tableView isEqual:self.myTableView] && section == 0) {
		result = 30.0f;
	}

	return result;
}

TableView-9

  • tableView:titleForHeaderInSection:

The return value of this method is of type NSString. This string will automatically be placed inside a label by the table view and will be displayed as the header of the section, which is specified in the titleForHeaderInSection parameter.

  • tableView:titleForFooterInSection:

The return value of this method is of type NSString. This string will automatically be placed inside a label by the table view and will be displayed as the footer of the section, which is specified in the titleForFooterInSection parameter.