[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
UIView *lineView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 0.35)];
lineView.backgroundColor=[UIColor blackColor];
[self.contentView addSubview:lineView];
#import "MainViewController.h"
#import "GroupCell.h"
@interface MainViewController ()
@property (nonatomic,strong)UITableView *tableView;
@end
@implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setTitle:@"QQ分组"];
[self.view setBackgroundColor:[UIColor whiteColor]];
[self setTableView:[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain]];
[self.tableView setDataSource:self];
[self.tableView setDelegate:self];
[self.tableView registerClass:[GroupCell class] forCellReuseIdentifier:@"GroupCell"];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.view addSubview:self.tableView];
}
#pragma mark -Table view delegate -
#pragma mark -Table view data Source -
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 5;
}
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
GroupCell *cell= [tableView dequeueReusableCellWithIdentifier:@"GroupCell"];
if(!cell){
}
return cell ;
}
@end
重写:防止赋值的时候不匹配导致程序崩溃
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
frends需要重写他的set函数
- (void)setFriends:(NSArray *)friends{
NSMutableArray *tempArray=[NSMutableArray array];
for(NSDictionary *dataDict in friends){
FriendModel *model=[[FriendModel alloc]init];
[model setValuesForKeysWithDictionary:dataDict];
[tempArray addObject:model];
}
_friends=[tempArray copy];
}
GroupModel.m中定义类函数
+(instancetype)modelWithDict:(NSDictionary *)dict{
GroupModel *model=[[GroupModel alloc] init];
[model setValuesForKeysWithDictionary:dict];
return model;
}
MainViewController.m中懒加载方式获取数据
-(NSArray *)groupArray{
if(!_groupArray){
NSString *path=[[NSBundle mainBundle]pathForResource:@"qq_group" ofType:@"plist"];
NSArray *groupArrayFile=[NSArray arrayWithContentsOfFile:path];
NSMutableArray *tempArray=[NSMutableArray array];
for(NSDictionary *dic in groupArrayFile){
GroupModel *model=[GroupModel modelWithDict:dic];
[tempArray addObject:model];
}
_groupArray=[tempArray copy];
}
return _groupArray;
}
该函数里给子视图的图片名,文本内容赋值
-(void)updateWithFriendModel:(FriendModel *)model{
[self.avatarImageView setImage:[UIImage imageNamed:model.icon]];
[self.titleLabel setText:model.name];
[self.subtitleLabel setText:model.message];
}
没注册:
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
GroupCell *cell= [tableView dequeueReusableCellWithIdentifier:@"GroupCell"];
if(!cell){
cell=[[GroupCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GroupCell"];
}
GroupModel *groupModel=self.groupArray[indexPath.section];
[cell updateWithFriendModel:groupModel.friends[indexPath.row]];
return cell ;
}
注册:
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
GroupCell *cell= [tableView dequeueReusableCellWithIdentifier:@"GroupCell"];
GroupModel *groupModel=self.groupArray[indexPath.section];
[cell updateWithFriendModel:groupModel.friends[indexPath.row]];
return cell ;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 40;
}
//如果没有下面这个函数,上面那个函数不起作用。
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.groupArray.count;
}
#import
#import "FriendModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface GroupCell : UITableViewCell
@property (nonatomic,strong)UIImageView *avatarImageView;
@property (nonatomic,strong)UILabel *titleLabel;
@property (nonatomic,strong)UILabel *subtitleLabel;
-(void)updateWithFriendModel:(FriendModel *)model;
@end
cell的内容用的都是groupModel.friends[indexPath.row]],friendModel
#import "GroupCell.h"
@implementation GroupCell
/*- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}*/
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[self setAvatarImageView:[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 60, 60)]];
[self.contentView addSubview:self.avatarImageView];
[self setTitleLabel:[[UILabel alloc]initWithFrame:CGRectMake(75, 7, 120, 21)]];
[self.contentView addSubview:self.titleLabel];
[self setSubtitleLabel:[[UILabel alloc]initWithFrame:CGRectMake(75, 34, 250, 21)]];
[self.contentView addSubview:self.subtitleLabel];
UIView *lineView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 0.35)];
lineView.backgroundColor=[UIColor blackColor];
[self.contentView addSubview:lineView];
}
return self;
}
-(void)updateWithFriendModel:(FriendModel *)model{
[self.avatarImageView setImage:[UIImage imageNamed:model.icon]];
[self.titleLabel setText:model.name];
[self.subtitleLabel setText:model.message];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
GroupHeaderView继承自UITableViewHeaderFooterView
HeaderButton继承自UIButton
图像按原大小居中显示(按图标的具体情况,本代码没有使用居中,因为会使图片显示异常):
[button.imageView setContentMode:UIViewContentModeCenter];
重新规划image view的矩形区域:
-(CGRect)imageRectForContentRect:(CGRect)contentRect{
CGFloat height=CGRectGetHeight(contentRect);
return CGRectMake(0, 0, height, height);
}
-(CGRect)titleRectForContentRect:(CGRect)contentRect{
return CGRectMake(40, 0, CGRectGetWidth(contentRect)-55, CGRectGetHeight(contentRect));
}
#import "HeaderButton.h"
@implementation HeaderButton
+(instancetype)buttonWithTarget:(id)target action:(SEL)action{
HeaderButton *button=[self buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 40)];
[button setBackgroundColor:[UIColor blackColor]];
[button.titleLabel setFont:[UIFont systemFontOfSize:18]];
[button.titleLabel setTextColor:[UIColor whiteColor]];
[button.layer setBorderColor:[UIColor whiteColor].CGColor];
[button.layer setBorderWidth:0.5];
[button setImage:[UIImage imageNamed:@"b.png"] forState:UIControlStateNormal];
//[button.imageView setContentMode:UIViewContentModeCenter];//图像居中
[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
return button;
}
-(CGRect)imageRectForContentRect:(CGRect)contentRect{
CGFloat height=CGRectGetHeight(contentRect);
return CGRectMake(0, 0, height, height);
}
-(CGRect)titleRectForContentRect:(CGRect)contentRect{
return CGRectMake(40, 0, CGRectGetWidth(contentRect)-55, CGRectGetHeight(contentRect));
}
@end
GroupHeaderView中去添加button,并指明和实现相应函数。
定义的方法要用initWithReuseIdentifier,完成button的创建。
按更新数据展示的update函数,按model实现button的文本,图标的转向,如果打开了isOpen为1,则翻转90度,如果为0,则保持翻转前的状态,一开始都是0.。
声明一个isOpen值只是用于在函数调用的时候给个参数,值是多少并不影响。
用block的方式给按钮的响应函数定义,具体的block内容在MainViewController.m中定义。
@property (nonatomic,assign,readonly)BOOL isOpen;
#import
#import "HeaderButton.h"
#import "GroupModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface GroupHeaderView : UITableViewHeaderFooterView
@property (nonatomic,strong) HeaderButton *headerButton;
@property (nonatomic,assign,readonly)BOOL isOpen;
@property (nonatomic,copy)void (^openHandler)(BOOL isOpen);
-(void)updateHeaderViewWithModel:(GroupModel*)model;
@end
#import "GroupHeaderView.h"
@implementation GroupHeaderView
-(instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier{
self=[super initWithReuseIdentifier:reuseIdentifier];
if(self){
[self setHeaderButton:[HeaderButton buttonWithTarget:self action:@selector(headerButtonClicked:)]];
[self.contentView addSubview:self.headerButton];
}
return self;
}
-(void)updateHeaderViewWithModel:(GroupModel *)model{
[self.headerButton setTitle:[NSString stringWithFormat:@"%@ (%@)",model.title,model.online] forState:UIControlStateNormal];
if(model.isOpen){
[self.headerButton.imageView setTransform:CGAffineTransformMakeRotation(M_PI_2)];
}
else{
[self.headerButton.imageView setTransform:CGAffineTransformIdentity];
}
_isOpen=!model.isOpen;
}
#pragma mark -Actions -
-(void)headerButtonClicked:(HeaderButton*)sender{
self.openHandler(_isOpen);
}
@end
cell的内容用的都是groupModel.friends[indexPath.row]],friendModel。
header的内容才用到:groupMode.title,groupMode.online
注册重用的header view:
self.tableView registerClass:[GroupHeaderView class] forHeaderFooterViewReuseIdentifier:@"HeaderView"];
设置block:
[headerView setOpenHandler:^(BOOL isOpen) {
groupModel.isOpen=!groupModel.isOpen;
[tableView reloadData];
是否展开,是按model.isOpen返回numberOfRowsInSection。
#import "MainViewController.h"
#import "GroupCell.h"
#import "GroupModel.h"
#import "FriendModel.h"
#import "GroupHeaderView.h"
@interface MainViewController ()
@property (nonatomic,strong)UITableView *tableView;
@property (nonatomic,strong)NSArray *groupArray;
@end
@implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self setTitle:@"QQ分组"];
[self.view setBackgroundColor:[UIColor whiteColor]];
[self setTableView:[[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain]];
[self.tableView setDataSource:self];
[self.tableView setDelegate:self];
[self.tableView registerClass:[GroupCell class] forCellReuseIdentifier:@"GroupCell"];
[self.tableView registerClass:[GroupHeaderView class] forHeaderFooterViewReuseIdentifier:@"HeaderView"];
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.view addSubview:self.tableView];
}
-(NSArray *)groupArray{
if(!_groupArray){
NSString *path=[[NSBundle mainBundle]pathForResource:@"qq_group" ofType:@"plist"];
NSArray *groupArrayFile=[NSArray arrayWithContentsOfFile:path];
NSMutableArray *tempArray=[NSMutableArray array];
for(NSDictionary *dic in groupArrayFile){
GroupModel *model=[GroupModel modelWithDict:dic];
[tempArray addObject:model];
}
_groupArray=[tempArray copy];
}
return _groupArray;
}
#pragma mark -Table view delegate -
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 40;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
GroupHeaderView *headerView=[tableView dequeueReusableHeaderFooterViewWithIdentifier:@"HeaderView"];
GroupModel *groupModel=self.groupArray[section];
[headerView updateHeaderViewWithModel:groupModel];
[headerView setOpenHandler:^(BOOL isOpen) {
groupModel.isOpen=!groupModel.isOpen;
[tableView reloadData];
}];
return headerView;
}
#pragma mark -Table view data Source -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.groupArray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
GroupModel *model=self.groupArray[section];
return model.isOpen? model.friends.count:0;
}
-(UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
GroupCell *cell= [tableView dequeueReusableCellWithIdentifier:@"GroupCell"];
GroupModel *groupModel=self.groupArray[indexPath.section];
[cell updateWithFriendModel:groupModel.friends[indexPath.row]];
return cell ;
}
@end
demo