一、Model
1 // 2 // FriendsModel.h 3 // IOS_0111_好友列表 4 // 5 // Created by ma c on 16/1/11. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface FriendsModel : NSObject 12 13 @property (nonatomic, copy) NSString *icon; 14 @property (nonatomic, copy) NSString *intro; 15 @property (nonatomic, copy) NSString *name; 16 @property (nonatomic, assign, getter=isVip) BOOL vip; 17 18 - (instancetype)initWithDict:(NSDictionary *)dict; 19 + (instancetype)friendsModelWithDict:(NSDictionary *)dict; 20 21 @end 22 23 // 24 // FriendsModel.m 25 // IOS_0111_好友列表 26 // 27 // Created by ma c on 16/1/11. 28 // Copyright (c) 2016年 博文科技. All rights reserved. 29 // 30 31 #import "FriendsModel.h" 32 33 @implementation FriendsModel 34 35 - (instancetype) initWithDict:(NSDictionary *)dict 36 { 37 if (self = [super init]) { 38 [self setValuesForKeysWithDictionary:dict]; 39 40 } 41 return self; 42 } 43 44 + (instancetype)friendsModelWithDict:(NSDictionary *)dict 45 { 46 return [[self alloc] initWithDict:dict]; 47 } 48 49 @end
1 // 2 // GroupModel.h 3 // IOS_0111_好友列表 4 // 5 // Created by ma c on 16/1/11. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 @interface GroupModel : NSObject 12 13 @property (nonatomic, copy) NSString *name; 14 @property (nonatomic, assign) NSInteger online; 15 @property (nonatomic, strong) NSArray *friends; 16 //设置组是否可见 17 @property (nonatomic, assign, getter=isVisible) BOOL visible; 18 19 - (instancetype)initWithDict:(NSDictionary *)dict; 20 + (instancetype)groupWithDict:(NSDictionary *)dict; 21 22 @end 23 24 25 // 26 // GroupModel.m 27 // IOS_0111_好友列表 28 // 29 // Created by ma c on 16/1/11. 30 // Copyright (c) 2016年 博文科技. All rights reserved. 31 // 32 33 #import "GroupModel.h" 34 #import "FriendsModel.h" 35 36 @implementation GroupModel 37 38 - (instancetype)initWithDict:(NSDictionary *)dict 39 { 40 if (self = [self init]) { 41 [self setValuesForKeysWithDictionary:dict]; 42 43 // 创建一个可变数组用来存放当前组中所有好友的模型 44 NSMutableArray *friendArr = [NSMutableArray array]; 45 // 遍历当前组中所有好友的字典数组,所字典数组转换成模型数组 46 for (NSDictionary *dict in self.friends) { 47 // 把当前的好友字典转换成好友模型 48 FriendsModel *model = [FriendsModel friendsModelWithDict:dict]; 49 // 把好友模型添加到数组中 50 [friendArr addObject:model]; 51 } 52 // 把装有当前组所有好友的模型数组赋值给组模型的friends属性 53 _friends =friendArr; 54 } 55 return self; 56 } 57 58 + (instancetype)groupWithDict:(NSDictionary *)dict 59 { 60 return [[self alloc] initWithDict:dict]; 61 } 62 63 @end
二、View
1 // 2 // FriendTableViewCell.h 3 // IOS_0111_好友列表 4 // 5 // Created by ma c on 16/1/11. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 @class FriendsModel; 11 @interface FriendTableViewCell : UITableViewCell 12 13 @property (nonatomic, strong) FriendsModel *friendModel; 14 15 + (instancetype)friendCellWithTableView:(UITableView *)tableView; 16 17 @end 18 19 // 20 // FriendTableViewCell.m 21 // IOS_0111_好友列表 22 // 23 // Created by ma c on 16/1/11. 24 // Copyright (c) 2016年 博文科技. All rights reserved. 25 // 26 27 #import "FriendTableViewCell.h" 28 #import "FriendsModel.h" 29 30 @implementation FriendTableViewCell 31 32 //创建单元格 33 + (instancetype)friendCellWithTableView:(UITableView *)tableView 34 { 35 static NSString *cellIdentifier = @"cellIdentifier"; 36 FriendTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 37 if (!cell) { 38 cell = [[FriendTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; 39 } 40 return cell; 41 } 42 //设置单元格数据 43 - (void)setFriendModel:(FriendsModel *)friendModel 44 { 45 _friendModel = friendModel; 46 //NSLog(@"%@",_friendModel.icon); 47 48 //把模型数据设置给子控件 49 self.imageView.image = [UIImage imageNamed:_friendModel.icon]; 50 self.textLabel.text = _friendModel.name; 51 self.detailTextLabel.text = _friendModel.intro; 52 53 //根据当前好友是不是VIP来决定是否将昵称显示为红色 54 self.textLabel.textColor = _friendModel.vip ? [UIColor redColor] : [UIColor blackColor]; 55 56 } 57 58 - (void)awakeFromNib { 59 // Initialization code 60 } 61 62 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 63 [super setSelected:selected animated:animated]; 64 65 // Configure the view for the selected state 66 } 67 68 @end
1 // 2 // GroupHeaderView.h 3 // IOS_0111_好友列表 4 // 5 // Created by ma c on 16/1/11. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @class GroupHeaderView; 12 @protocol GroupHeaderViewDelegate<NSObject> 13 14 - (void)groupHeaderViewDidClickTitleButton:(GroupHeaderView *)groupHeaderView; 15 16 @end 17 18 @class GroupModel; 19 @interface GroupHeaderView : UITableViewHeaderFooterView 20 21 @property (nonatomic, strong) GroupModel *groupModel; 22 23 //增加一个代理属性 24 @property (nonatomic, weak) id<GroupHeaderViewDelegate> delegate; 25 26 + (instancetype)groupHeaderViewWithTableView:(UITableView *)tableView; 27 28 @end 29 30 31 // 32 // GroupHeaderView.m 33 // IOS_0111_好友列表 34 // 35 // Created by ma c on 16/1/11. 36 // Copyright (c) 2016年 博文科技. All rights reserved. 37 // 38 39 #import "GroupHeaderView.h" 40 #import "GroupModel.h" 41 42 @interface GroupHeaderView () 43 44 @property (nonatomic, strong) UIButton *btnGroupTitle; 45 @property (nonatomic, strong) UILabel *lblCount; 46 47 @end 48 49 @implementation GroupHeaderView 50 51 #pragma mark - groupHeaderViewWithTableView方法 52 //封装一个类方法,创建GroupHeaderView 53 + (instancetype)groupHeaderViewWithTableView:(UITableView *)tableView 54 { 55 static NSString *ID = @"UITableViewHeaderFooterView"; 56 GroupHeaderView *HeaderView = [tableView dequeueReusableCellWithIdentifier:ID]; 57 if (HeaderView == nil) { 58 HeaderView = [[GroupHeaderView alloc] initWithReuseIdentifier:ID]; 59 } 60 return HeaderView; 61 } 62 63 #pragma mark - initWithReuseIdentifier方法 64 //重写initWithReuseIdentifier:方法,在创建GroupHeaderView时,同时创建子控件 65 - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier 66 { 67 if (self = [super initWithReuseIdentifier:reuseIdentifier]) { 68 //创建按钮 69 self.btnGroupTitle = [[UIButton alloc] init]; 70 //设置图片 71 [self.btnGroupTitle setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; 72 //设置按钮背景图片 73 [self.btnGroupTitle setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; 74 [self.btnGroupTitle setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; 75 //设置按钮中整体内容左对齐 76 self.btnGroupTitle.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 77 //设置按钮内容的内边距 78 self.btnGroupTitle.contentEdgeInsets = UIEdgeInsetsMake(0, 16, 0, 0); 79 //设置按钮标题距离左边的边距 80 [self.btnGroupTitle setTitleEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)]; 81 //设置按钮中图片的显示模式 82 self.btnGroupTitle.imageView.contentMode = UIViewContentModeCenter; 83 //让图片框超出的部分不要截掉 84 self.btnGroupTitle.imageView.clipsToBounds = NO; 85 //点击事件 86 [self.btnGroupTitle addTarget:self action:@selector(btnGroupTitleClick) forControlEvents:UIControlEventTouchUpInside]; 87 //加载到视图 88 [self.contentView addSubview:self.btnGroupTitle]; 89 90 //创建Label 91 self.lblCount = [[UILabel alloc] init]; 92 [self.contentView addSubview:self.lblCount]; 93 } 94 return self; 95 } 96 //组标题按钮的点击事件 97 - (void)btnGroupTitleClick 98 { 99 //1.设置组的状态 100 self.groupModel.visible = !self.groupModel.isVisible; 101 //2.刷新TableView的数据 102 if (self.delegate != nil && [self.delegate respondsToSelector:@selector(groupHeaderViewDidClickTitleButton:)]) { 103 //调用代理方法 104 [self.delegate groupHeaderViewDidClickTitleButton:self]; 105 } 106 } 107 #pragma mark - didMoveToSuperview方法 108 //当一个新的headerView已经加载到父控件中执行这个方法 109 - (void)didMoveToSuperview 110 { 111 if (self.groupModel.visible ) { 112 //让按钮中的图片旋转 113 self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); 114 } 115 else 116 //让按钮中的图片旋转 117 self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(0); 118 } 119 #pragma mark - setGroupModel方法 120 //重写setGroupModel方法 121 - (void)setGroupModel:(GroupModel *)groupModel 122 { 123 _groupModel = groupModel; 124 //设置数据 125 126 //设置按钮上的文字 127 [self.btnGroupTitle setTitle:_groupModel.name forState:UIControlStateNormal]; 128 [self.btnGroupTitle setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 129 130 //设置Label上的文字 131 self.lblCount.text = [NSString stringWithFormat:@"%lu / %lu",_groupModel.online,_groupModel.friends.count]; 132 133 //解决按钮中的图片旋转问题 134 if (self.groupModel.visible ) { 135 //让按钮中的图片旋转 136 self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); 137 } 138 else 139 //让按钮中的图片旋转 140 self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(0); 141 142 //不要在这里设置frame,因为当前控件的frame为0; 143 144 } 145 #pragma mark - layoutSubviews方法 146 //当前控件的frame发生改变调用这个方法 147 - (void)layoutSubviews 148 { 149 [super layoutSubviews]; 150 151 //设置frame 152 153 self.btnGroupTitle.frame = self.bounds; 154 155 CGFloat lblW = 100; 156 CGFloat lblH = self.bounds.size.height; 157 CGFloat lblX = self.bounds.size.width - 10 - lblW; 158 CGFloat lblY = 0; 159 self.lblCount.frame = CGRectMake(lblX, lblY, lblW, lblH); 160 161 } 162 163 /* 164 // Only override drawRect: if you perform custom drawing. 165 // An empty implementation adversely affects performance during animation. 166 - (void)drawRect:(CGRect)rect { 167 // Drawing code 168 } 169 */ 170 171 @end
三、Controller
1 // 2 // QQFriendsTableVC.m 3 // IOS_0111_好友列表 4 // 5 // Created by ma c on 16/1/11. 6 // Copyright (c) 2016年 博文科技. All rights reserved. 7 // 8 9 #import "QQFriendsTableVC.h" 10 #import "GroupModel.h" 11 #import "FriendsModel.h" 12 #import "FriendTableViewCell.h" 13 #import "GroupHeaderView.h" 14 15 @interface QQFriendsTableVC ()<GroupHeaderViewDelegate> 16 17 @property (nonatomic, strong) NSArray *groupArr; 18 19 @end 20 21 @implementation QQFriendsTableVC 22 23 #pragma mark - 懒加载 24 - (NSArray *)groupArr 25 { 26 if (_groupArr == nil) { 27 NSString *path = [[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil]; 28 NSArray *arrDict = [NSArray arrayWithContentsOfFile:path]; 29 30 NSMutableArray *arrModel = [NSMutableArray array]; 31 for (NSDictionary *dict in arrDict) { 32 33 GroupModel *model = [GroupModel groupWithDict:dict]; 34 35 [arrModel addObject:model]; 36 37 } 38 _groupArr =arrModel; 39 } 40 return _groupArr; 41 42 } 43 #pragma mark - 数据源方法 44 //组数 45 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 46 { 47 return self.groupArr.count; 48 } 49 //每组行数 50 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 51 { 52 GroupModel *model = self.groupArr[section]; 53 if (model.visible == NO) { 54 return 0; 55 } 56 else 57 return model.friends.count; 58 } 59 //设置单元格 60 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 61 { 62 //1.获取模型 63 GroupModel *groupModel = self.groupArr[indexPath.section]; 64 FriendsModel *friendsModel = groupModel.friends[indexPath.row]; 65 66 //2.创建单元格 67 FriendTableViewCell *cell = [FriendTableViewCell friendCellWithTableView:tableView]; 68 69 //3.设置单元格内容 70 cell.friendModel = friendsModel; 71 72 //4.返回单元格 73 return cell; 74 } 75 ////设置每一组的组标题(只能设置字符串,但我们每一组还包含其他子控件) 76 //- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 77 //{ 78 // GroupModel *groupModel = self.groupArr[section]; 79 // return groupModel.name; 80 //} 81 82 //设置HeaderView 83 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 84 { 85 //不要创建一个UIView返回,因为无法重用 86 //为了重用每个Header中的UIView,这里要返回UITableViewHeaderFooterView 87 88 //1.获取模型 89 GroupModel *groupModel = self.groupArr[section]; 90 //2.创建UITableViewHeaderFooterView 91 GroupHeaderView *HeaderView = [GroupHeaderView groupHeaderViewWithTableView:tableView]; 92 //因为刚创建好的HeaderView没有设置frame,所以frame为0,但是运行以后我们看到都是有frame 93 //原因UITableView要用到HeaderView,会根据一些设置动态为HeaderView的frame赋值 94 //3.设置数据 95 HeaderView.groupModel = groupModel; 96 //设置组的标志 97 HeaderView.tag = section; 98 //设置代理 99 HeaderView.delegate = self; 100 //4.返回view 101 return HeaderView; 102 103 104 } 105 #pragma mark - viewDidLoad方法 106 - (void)viewDidLoad 107 { 108 [super viewDidLoad]; 109 self.tableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; 110 //统一设置每组标题的高度 111 self.tableView.sectionHeaderHeight = 44; 112 self.tableView.tableFooterView = [[UIView alloc] init]; 113 } 114 #pragma mark - GroupHeaderViewDelegate代理方法 115 - (void)groupHeaderViewDidClickTitleButton:(GroupHeaderView *)groupHeaderView 116 { 117 //刷新TableView 118 // [self.tableView reloadData]; 119 //局部刷新 120 NSIndexSet *indexSet = [[NSIndexSet alloc] initWithIndex:groupHeaderView.tag]; 121 [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationFade]; 122 } 123 124 #pragma mark - 隐藏状态栏 125 - (BOOL)prefersStatusBarHidden 126 { 127 return YES; 128 } 129 130 131 @end