-
准备工作:
好友列表plist文件
头像:
- 第一步,创建数据模型,根据Plist文件创建
- 好友Model
#import
@interface JFriendsModel : NSObject
@property(nonatomic, copy) NSString * icon; // 头像
@property(nonatomic, copy) NSString * name; // 姓名
@property(nonatomic, copy) NSString * intro; // 签名
@property(nonatomic, assign) BOOL isVip; // vip
- (instancetype)initWithDict:(NSDictionary *)dict; // 初始化方法
+ (instancetype)friendWithDict:(NSDictionary *)dict; // 遍历构造器
@end```
- 方法实现
import "JFriendsModel.h"
@implementation JFriendsModel
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
- (instancetype)friendWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end```
- Section模型的创建与好友模型创建的方法大致相同
#import
@class JFriendsModel;
@interface JGroupModel : NSObject
@property (nonatomic, copy) NSString *name; // 分组名称
@property (nonatomic, copy) NSString *online; // 在线人数
@property (nonatomic, strong) NSArray *friends; // 好友数组
@property(nonatomic, strong) JFriendsModel * friendModel; // 好友Model
@property(nonatomic, assign) BOOL isOpen; // 点击展开或者关闭状态
- (instancetype)initWithDict:(NSDictionary *)dict; // 初始化方法
+ (instancetype)groupWithDict:(NSDictionary *)dict; // 遍历构造器
@end```
- 方法实现
import "JGroupModel.h"
import "JFriendsModel.h"
@implementation JGroupModel
/**
- 初始化方法
- @param dict 外界传过来的字典
- @return self
*/
- (instancetype)initWithDict:(NSDictionary *)dict
{
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict]; // 赋值
NSMutableArray *array = [NSMutableArray arrayWithCapacity:self.friends.count]; // 创建可变数组
for (NSDictionary *dict in self.friends) { // 遍历好友数组
JFriendsModel *friendModel = [JFriendsModel friendWithDict:dict]; // 初始化好友模型
[array addObject:friendModel]; // 装入可变数组
}
self.friends = array; // 赋值给好友数组
}
return self;
}
/**
- 遍历构造器
- @param dict 外界传入的字典
- @return self实例对象
*/
- (instancetype)groupWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end```
- 模型创建好之后,我们来写一个继承自UITableViewHeaderFooterView的头视图View
#import
#import "JGroupModel.h"
/**
* 头视图的代理方法
*/
@protocol HeaderViewDelegate
@optional
- (void)clickView; // 点击头视图事件
@end
@interface HeaderView : UITableViewHeaderFooterView
@property (nonatomic, assign) id delegate; // 代理
@property (nonatomic, strong) JGroupModel *groupModel; // 头视图数据模型
+ (instancetype)headerView:(UITableView *)tableView; // 初始化方法
@end```
- 方法实现
import "HeaderView.h"
import "JGroupModel.h"
@implementation HeaderView{
UIButton *_arrowButton; // 点击按钮
UILabel *_label; // 标题
}
- (instancetype)headerView:(UITableView *)tableView
{
static NSString *identifier = @"header"; // 重用
HeaderView *headerView = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!headerView) {
headerView = [[HeaderView alloc] initWithReuseIdentifier:identifier];
}
return headerView;
}
-
(instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if (self == [super init]) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setBackgroundImage:[UIImage imageNamed:@"header_bg"] forState:UIControlStateNormal]; // 背景图片
[button setBackgroundImage:[UIImage imageNamed:@"header_bg_highlighted"] forState:UIControlStateHighlighted]; // 点击状态下的背景图片
[button setImage:[UIImage imageNamed:@"arrow"] forState:UIControlStateNormal]; // 图片
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; // button文字颜色
// 设置Button按钮内容的内边距
[button setContentEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)];
// 设置Button内容的位置居左
[button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
// 设置Button标题的内边距
[button setTitleEdgeInsets:UIEdgeInsetsMake(0, 20, 0, 0)];
// 设置button图片的位置
[button setImageEdgeInsets:UIEdgeInsetsMake(0, 10, 0, 0)];
[button addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
button.imageView.clipsToBounds = NO; // 取消button图片自动修剪属性
_arrowButton = button; // 赋值
[self addSubview:_arrowButton];// 创建label显示在线人数 UILabel *labelRight = [[UILabel alloc] init]; labelRight.textAlignment = NSTextAlignmentCenter; _label = labelRight; [self addSubview:_label];
}
return self;
}
pragma mark - buttonAction
-
(void)buttonAction
{
self.groupModel.isOpen = !self.groupModel.isOpen; // 设置属性为非// 如果代理响应了代理方法,就要调用这个方法
if ([self.delegate respondsToSelector:@selector(clickView)]) {
[self.delegate clickView];
}
}
pragma mark - 调用系统方法对button的箭头图片实现旋转
- (void)didMoveToSuperview
{
// 根据isOpen属性判断是否旋转?如果为YES,则旋转90°,否则不旋转
_arrowButton.imageView.transform = self.groupModel.isOpen ? CGAffineTransformMakeRotation(M_PI_2) : CGAffineTransformMakeRotation(0);
}
pragma mark - 系统方法设置Frame值
- (void)layoutSubviews
{
[super layoutSubviews];
_arrowButton.frame = self.bounds; // 注意这里要设置为bounds 不然会出错
_label.frame = CGRectMake(self.frame.size.width - 70, 0, 60, self.frame.size.height);
}
pragma mark - 属性set方法给控件赋值
(void)setGroupModel:(JGroupModel *)groupModel
{
_groupModel = groupModel;
[_arrowButton setTitle:_groupModel.name forState:UIControlStateNormal]; // button标题
_label.text = [NSString stringWithFormat:@"%@/%lu", _groupModel.online, (unsigned long)_groupModel.friends.count]; // label文字
}
@end```UITableView的头视图 和 模型都创建好了 我们来写最后的主角,主TableView
#import "ListTableViewController.h"
#import "JGroupModel.h"
#import "JFriendsModel.h"
#import "HeaderView.h"
#import "ViewController.h"
@interface ListTableViewController () // 遵守代理
@property (nonatomic, strong) NSArray *dataArray; // 数据数组
@end
@implementation ListTableViewController
// 懒加载
- (NSArray *)dataArray
{
if (!_dataArray) {
// 获取数据
NSString *path = [[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil];
NSArray *array = [NSArray arrayWithContentsOfFile:path];
NSLog(@"%@", array);
// 初始化可变数组,数量为获取到的数组的数量
NSMutableArray *muArray = [NSMutableArray arrayWithCapacity:array.count];
// 遍历
for (NSDictionary *dict in array) {
// 初始化分组模型
JGroupModel *md = [JGroupModel groupWithDict:dict];
// 添加至可变数组
[muArray addObject:md];
}
// 赋值给本控制器数据数组
_dataArray = [muArray copy];
}
return _dataArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
// 重设tableHeaderView的高度
self.tableView.sectionHeaderHeight = 40;
// 取出tableView多余的分割线
[self clickExtraLine:self.tableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.dataArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
JGroupModel *md = self.dataArray[section];
// 判断是展开还是关闭,如果是展开则返回friend的个数,如果是关闭则返回0
NSInteger count = md.isOpen ? md.friends.count : 0;
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"friendCell";
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
// 以上不能用forIndexPath:indexPath这个方法,不然会出现重用的崩溃
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
JGroupModel *md = self.dataArray[indexPath.section]; // 现获取分组模型
JFriendsModel *friendMd = md.friends[indexPath.row]; // 获取row模型
// 赋值
cell.imageView.image = [UIImage imageNamed:friendMd.icon];
cell.textLabel.text = friendMd.name;
cell.detailTextLabel.text = friendMd.intro;
return cell;
}
// 点击进入详情
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ViewController *vc = [[ViewController alloc] init];
vc.view.backgroundColor = [UIColor redColor];
[self.navigationController pushViewController:vc animated:YES];
}
#pragma mark - UITableView Delegate
// 添加头视图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
HeaderView *headView = [HeaderView headerView:tableView];
headView.delegate = self;
headView.groupModel = self.dataArray[section]; // 给头视图传递数据模型
return headView;
}
#pragma mark - 代理方法的实现
- (void)clickView
{
[self.tableView reloadData];
}
#pragma mark - 去掉多余的线
- (void)clickExtraLine:(UITableView *)tableView
{
UIView *view = [[UIView alloc] init];
view.backgroundColor = [UIColor clearColor];
[self.tableView setTableFooterView:view];
}
@end```
- 运行效果:
![QQList.gif](http://upload-images.jianshu.io/upload_images/189984-c5d1acad818a88f5.gif?imageView2/2/w/1240)