1,除可以为TableView设置Header/Footer文字外,还可以设置View,这个view如果是单独定义的CLASS,需要继承自UITableViewHeaderFooterView
2,当父控件的FRAME发生改变时,会自动调用子控件的layoutSubView方法,可重写此方法,对子控件进行重写布局,但此重写方法第一行必须先调用相同的父类方法
TableView中的三个数据源方法一旦确定,也就自动确定了每个section的头部/尾部FRAME,这里是自动改变的,可以在UITableViewHeaderFooterView中重写layoutSubView方法,这个方法也是自动调的
3,TableViewHeaderFooterView像TableViewCell一样可以被TableView自动放入到缓存池中进行回收利用,但relaodData方法是重写创建Cell或HeaderFooterView的,实际上是重写创建的,和旧的内存地址是不一样的;当一个控件被添加到父类中时,会自动调用:didMoveToSuperview
#import
@class TXFriendGroup, TXFriendHeaderView;
@protocol TXFriendHeaderViewDelegate
@optional
- (void)friendHeaderViewDidClickedNameView:(TXFriendHeaderView *)headerView;
@end
@interface TXFriendHeaderView : UITableViewHeaderFooterView
@property (nonatomic, weak) id
@property (nonatomic, strong) TXFriendGroup *group;
+ (instancetype)friendHeaderViewWithTableView:(UITableView *)tableView;
@end
=============
#import "TXFriendCell.h"
#import "TXFriend.h"
@implementation TXFriendCell
+ (instancetype)friendCellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"friendCell";
TXFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[TXFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
return cell;
}
- (void)setFriendData:(TXFriend *)friendData
{
_friendData = friendData;
self.imageView.image = [UIImage imageNamed:friendData.icon];
self.textLabel.text = friendData.name;
self.textLabel.textColor = friendData.isVip ? [UIColor redColor] : [UIColor blackColor];
self.detailTextLabel.text = friendData.intro;
}
@end
============
#import "TXFriendHeaderView.h"
#import "TXFriendGroup.h"
@interface TXFriendHeaderView()
@property (nonatomic, weak) UIButton *nameView;
@property (nonatomic, weak) UILabel *countView;
@end
@implementation TXFriendHeaderView
+ (instancetype)friendHeaderViewWithTableView:(UITableView *)tableView
{
static NSString *ID = @"friendGroup";
TXFriendHeaderView *headerView = [tableView dequeueReusableCellWithIdentifier:ID];
if (headerView == nil) {
headerView = [[TXFriendHeaderView alloc] initWithReuseIdentifier:ID];
}
return headerView;
}
- (id)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithReuseIdentifier:reuseIdentifier];
if (self) {
// 1
UIButton *nameView = [UIButton buttonWithType:UIButtonTypeCustom];
[nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];
[nameView setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];
[nameView setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
[nameView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// Button内部有两个子控件,而控件一般是位于content中的,所以这里以conteng开头的水平对齐属性
nameView.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
nameView.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
nameView.titleEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
nameView.imageView.contentMode = UIViewContentModeCenter;
nameView.imageView.clipsToBounds = NO;
[nameView addTarget:self action:@selector(nameViewClicked) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:nameView];
self.nameView = nameView;
// 2
UILabel *countView = [[UILabel alloc] init];
// Label里面没有子控件了,直接写对齐属性
countView.textAlignment = NSTextAlignmentRight;
countView.textColor = [UIColor grayColor];
[self.contentView addSubview:countView];
self.countView = countView;
}
return self;
}
// 当父控件FRAME发生改变时,这个方法会被自动调用
// 父控件UITableHeaderFooterView 只要确定每一个组后,就会被自动放到每个section组的头部或尾部,这样他的FRAME就被改变了
- (void)layoutSubviews
{
[super layoutSubviews]; // 必须先调用父类的方法
self.nameView.frame = self.bounds;
CGFloat countW = 100;
CGFloat countH = self.bounds.size.height;
CGFloat countX = self.bounds.size.width - countW - 5;
CGFloat countY = 0;
self.countView.frame = CGRectMake(countX, countY, countW, countH);
[self didMoveToSuperview];//缓存池中取出的headerView可能那个三角形按钮是以前旧状态,所以再次调用一次检查
}
// 当前控件被添加到父控件时,就会自动调用下面的方面
- (void)didMoveToSuperview
{
if (self.group.isOpened) {
self.nameView.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
} else {
self.nameView.imageView.transform = CGAffineTransformMakeRotation(0);
}
}
- (void)setGroup:(TXFriendGroup *)group
{
_group = group;
[self.nameView setTitle:group.name forState:UIControlStateNormal];
self.countView.text = [NSString stringWithFormat:@"%@/%d ", group.online, group.friends.count];
}
- (void)nameViewClicked
{
self.group.opened = !self.group.isOpened;
if ([self.delegate respondsToSelector:@selector(friendHeaderViewDidClickedNameView:)]) {
[self.delegate friendHeaderViewDidClickedNameView:self];
}
}
@end
===================
#import "TXViewController.h"
#import "TXFriendGroup.h"
#import "TXFriendCell.h"
#import "TXFriendHeaderView.h"
@interface TXViewController ()
@property (nonatomic, strong) NSArray *groups;
@property (weak, nonatomic) IBOutlet UITableView *myTableView;
@end
@implementation TXViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView.rowHeight = 50;
self.myTableView.sectionHeaderHeight = 44;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.groups.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
TXFriendGroup *group = self.groups[section];
return group.isOpened ? group.friends.count : 0; // 子Cell关闭/显示 效果,其实就是控制组内部row的行数后,再刷新table
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
TXFriendCell *cell = [TXFriendCell friendCellWithTableView:tableView];
TXFriendGroup *group = self.groups[indexPath.section];
cell.friendData = group.friends[indexPath.row];
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
TXFriendHeaderView *headerView = [TXFriendHeaderView friendHeaderViewWithTableView:tableView];
headerView.group = self.groups[section];
headerView.delegate = self;
return headerView;
}
- (void)friendHeaderViewDidClickedNameView:(TXFriendHeaderView *)headerView
{
[self.myTableView reloadData];
}
- (NSArray *)groups
{
if(_groups == nil)
{
NSString *path = [[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil];
NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *groupArray = [NSMutableArray array];
for (NSDictionary *dict in dictArray) {
TXFriendGroup *group = [TXFriendGroup groupWithDict:dict];
[groupArray addObject:group];
}
_groups = groupArray;
}
return _groups;
}
- (BOOL)prefersStatusBarHidden
{
return YES;
}
@end
===================
#import
@class TXFriend;
@interface TXFriendCell : UITableViewCell
@property (nonatomic, strong) TXFriend *friendData;
+ (instancetype)friendCellWithTableView:(UITableView *)tableView;
@end