之前做这个是因为老师布置的作业,其实写出来好长一段时间了,但是由于自己比较忙,没有时间进行整理,现在才拿出来整理。
不说话,首先上效果图:
全部代码和相关的素材已经全部打包在GitHub上:https://github.com/canoejun/QQList
1.首先改变控制器
将控制器改为tableviewController,并在Main.storyboard中拖拽相应的tableviewcontroller,改变控制器所关联的类,设置DataSource和delegate。在所关联的类中修改继承的控制器。
2.在控制器类中实现相应的代理方法和读取信息数据
在本例子中没有采用网络端的传输数据,而是采用了plist文件进行QQ列表用户信息数据的存储。
首先根据plist文件建立相关的模型,模型.m文件不需要书写任何的东西,因为本例子中采用了MJ框架进行数据的解析,因此不需要手动在.m文件中转换数据了
GroupModel.h
#import <Foundation/Foundation.h>
@interface GroupModel : NSObject
/** 组名 */
@property (nonatomic, copy) NSString *groupname;
/** 组员 */
@property (nonatomic, copy) NSArray *friends;
/** 是否打开 */
@property (nonatomic, assign) BOOL isOpen;
@end
FriendModel.h
#import <Foundation/Foundation.h>
@interface FriendModel : NSObject
/** QQ好友昵称 */
@property (nonatomic,copy) NSString *name;
/** 状态 */
@property (nonatomic,copy) NSString *mode;
/** 头像 */
@property (nonatomic,copy) NSString * icon;
@end
建立数组,采用懒加载进行字典转模型向是数组中存储数据(别忘记导入相应的MJ框架)
@interface QQViewController ()<SectionHeadViewDelegate>
/** 保存模型数据的数组 */
@property (nonatomic,copy) NSArray *QQDataArray;
@end
-(NSArray *)QQDataArray{
if (!_QQDataArray) {
// 告诉group中array的成员是一个个的dictionary
[GroupModel mj_setupObjectClassInArray:^NSDictionary *{
return @{@"friends":[FriendModel class]};
}];
_QQDataArray = [GroupModel mj_objectArrayWithFilename:@"qq.plist"];
}
return _QQDataArray;
}
在主体部分就是进行cell和sectionHeader的宽度设定以及清除下方多余的cell
- (void)viewDidLoad {
[super viewDidLoad];
// 清除底部多余cell
[self.tableView setTableFooterView:[[UIView alloc] initWithFrame:CGRectZero]];
// 清除分割线
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.rowHeight = 50;
self.tableView.sectionHeaderHeight = 50;
}
3.实现代理的DataSource方法
当然在一开始,并没有直接将相关的方法写的那么详细准确,但是也要把可能用到的方法先写出来放在那里,后面再定义了相关的cell和sectionHeadView以后再回过来进行修改
#pragma mark ------ UITableviewDataSource方法 ------
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.QQDataArray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([self.QQDataArray[section] isOpen]) {
return [[self.QQDataArray[section] friends] count];
}else{
return 0;
}
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * ID = @"qq";
QQFriendTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:ID];
// 设置数据
GroupModel * group = self.QQDataArray[indexPath.section];
FriendModel * friend = group.friends[indexPath.row];
cell.friends = friend;
return cell;
}
//设置分组的headView
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
HeadView * view = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([HeadView class]) owner:nil options:nil] firstObject];
view.delegate = self;
view.group = _QQDataArray[section];
return view;
}
4.在tableview中自定义cell
在tableview里面进行xib的布局以后,然后将右边的class与新建的cell文件关联,将控件拖入到cell的.m文件中
QQFriendTableViewCell.h
#import <UIKit/UIKit.h>
@class FriendModel;
@interface QQFriendTableViewCell : UITableViewCell
/** 模型 */
@property (nonatomic,copy) FriendModel * friends;
@end
QQFriendTableViewCell.m
#import "QQFriendTableViewCell.h"
#import "FriendModel.h"
@interface QQFriendTableViewCell ()
@property (weak, nonatomic) IBOutlet UIImageView *iconImageView;
@property (weak, nonatomic) IBOutlet UILabel *nameLabel;
@property (weak, nonatomic) IBOutlet UILabel *modeLabel;
@end
@implementation QQFriendTableViewCell
//设置数据
- (void)setFriends:(FriendModel *)friends{
_friends = friends;
self.iconImageView.image = [UIImage imageNamed:friends.icon];
self.nameLabel.text = friends.name;
self.modeLabel.text = friends.mode;
}
@end
4.自定义sectionHeaderView
考虑到系统默认提供的sectionHeadView并不能够满足自己的需求,这时候需要自己重新定义相关的视图。本例子还是采用了xib建立一个新的View类。
如图所示,自定义了一个View,并布局。别忘记将右边的class设置为相应建立的HeadView类。这时候记得别把将File‘s Owner设置为headview了,File’s Owner只是对View中的逻辑操作进行处理的,考虑到这个例子中section不需要这样子,所以这边可以不要设置。
HeadView.h
#import <UIKit/UIKit.h>
@class HeadView,GroupModel;
@protocol SectionHeadViewDelegate<NSObject>
-(void)sectionHeadButtonDidClicked:(HeadView *)headView;
@end
@interface HeadView : UIView
/** 代理 */
@property (nonatomic,strong) id<SectionHeadViewDelegate>delegate;
/** 模型 */
@property (nonatomic,strong) GroupModel * group;
@end
HeadView.m
在按钮点击事件中,因为需要控制相应组的展开或者是收缩,一开始没有想好。后来想到了将这个判断和模型绑定到一块,所以在模型中才定义了一个 isOpen的布尔属性,用于判断是否需要展开或者是关闭。
#import "HeadView.h"
#import "GroupModel.h"
@interface HeadView ()
@property (weak, nonatomic) IBOutlet UIButton *pullButton;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UILabel *membersCountLabel;
@end
@implementation HeadView
-(void)awakeFromNib{
[super awakeFromNib];
[self.pullButton addTarget:self action:@selector(pullButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction)pullButtonClicked:(UIButton *)sender {
_group.isOpen = !_group.isOpen;
if ([self.delegate respondsToSelector:@selector(sectionHeadButtonDidClicked:)]) {
[self.delegate sectionHeadButtonDidClicked:self];
}
}
/*
* 协议方法会刷新tableview,然后会刷新tableview的viewForHeaderInSection:方法 就会重新布局headView所以会走layoutSubviews方法
*/
-(void)layoutSubviews{
if (!_group.isOpen) {
_pullButton.transform = CGAffineTransformMakeRotation(-M_PI_2);
}else{
_pullButton.transform = CGAffineTransformIdentity;
}
}
//设置数据
-(void)setGroup:(GroupModel *)group{
_group = group;
_titleLabel.text = group.groupname;
_membersCountLabel.text = [NSString stringWithFormat:@"%ld",group.friends.count];
}
@end
由于sectionHeadView的按钮点击事件,数据发生了改变,所以需要在主界面将数据刷新一下。本例子使用了协议完成。(有兴趣的可以使用block或者通知试一下)
在自己的主函数中完成协议的相关方法:
#pragma mark ------ 实现代理方法 ------
-(void)sectionHeadButtonDidClicked:(HeadView *)headView{
[self.tableView reloadData];
}
由于是本人能力有限,刚刚开始学习IOS开发,如有问题还望大家一一指出
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)