首页 > 代码库 > UI基础--UITableView实现仿QQ好友列表页面

UI基础--UITableView实现仿QQ好友列表页面

需求:类似于QQ好友列表页面的显示,有好友分组,有好友数量,在线人数,vip会员、展开分组时显示分组好友,合并分组时不显示:具体效果图如下:

技术分享技术分享

 

分析:

1、展开分组时显示分组好友,该功能可以使用显示UITableViewCell的数据即可;

2、分组头可以考虑使用一个headerView来实现;

 

示例文件结构:

技术分享

 

具体实现步骤:

1、自定义数据模型类,由于plist文件中包含了2个字典,所以需要写2个数据模型;

2、自定义cell属性包括数据模型以及生成可重用cell的方法,由于系统自带的子控件即可满足实际要求,所以不用写frame模型了;

4、自定义HeaderView,包括模型数据属性和快速构造HeaderView的类方法,以及代理方法;

5、在控制器中写UITableView的 数据显示的方法;

 

具体代码:

Model:

 

 1 // 2 //  JWFriend.h 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import <Foundation/Foundation.h>10 11 @interface JWFriend : NSObject12 @property (nonatomic,copy) NSString *icon;13 @property (nonatomic,copy) NSString *intro;14 @property (nonatomic,copy) NSString *name;15 @property (nonatomic,assign,getter=isVip) BOOL vip;16 - (instancetype)initWithDic:(NSDictionary *)dic;17 + (instancetype)friendWithDic:(NSDictionary *)dic;18 @end

 

 

 1 // 2 //  JWFriend.m 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import "JWFriend.h"10 11 @implementation JWFriend12 - (instancetype)initWithDic:(NSDictionary *)dic {13     if (self = [super init]) {14         [self setValuesForKeysWithDictionary:dic];//KVC的使用15     }16     return self;17 }18 + (instancetype)friendWithDic:(NSDictionary *)dic {19     return [[self alloc] initWithDic:dic];20 }21 @end

 

 1 // 2 //  JWFriendGroup.h 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import <Foundation/Foundation.h>10 11 @interface JWFriendGroup : NSObject12 @property (nonatomic,strong) NSArray *friends;13 @property (nonatomic,copy) NSString *name;14 @property (nonatomic,assign) int online;15 /*16  组头是否展开,默认为NO17  */18 @property (nonatomic,assign,getter=isExpend) BOOL expend;19 - (instancetype)initWithDic:(NSDictionary *)dic;20 + (instancetype)friendGroupWithDic:(NSDictionary *)dic;21 + (NSMutableArray *)friendGroupList;22 @end

 

 1 // 2 //  JWFriendGroup.m 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import "JWFriendGroup.h"10 #import "JWFriend.h"11 @implementation JWFriendGroup12 - (instancetype)initWithDic:(NSDictionary *)dic {13     if (self = [super init]) {14         [self setValuesForKeysWithDictionary:dic];15     }16     return self;17 }18 + (instancetype)friendGroupWithDic:(NSDictionary *)dic {19     return [[self alloc] initWithDic:dic];20 }21 22 + (NSMutableArray *)friendGroupList {23     NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends" ofType:@"plist"]];24     25     NSMutableArray *tempArray = [NSMutableArray array];26     27     for (NSDictionary *dic in array) {//字典转模型28         JWFriendGroup *friendGroup = [JWFriendGroup friendGroupWithDic:dic];29         30         NSMutableArray *tem = [NSMutableArray array];31         for (NSDictionary *dict in friendGroup.friends) {//模型里面还带有子弹,所以继续进行字典转模型步骤32             JWFriend *friend = [JWFriend friendWithDic:dict];33             [tem addObject:friend];34         }35         friendGroup.friends = tem;//转完模型后记得重新赋值36         [tempArray addObject:friendGroup];37     }38     return tempArray;39 }40 @end

 

View:

 1 // 2 //  JWFriendCell.h 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import <UIKit/UIKit.h>10 @class JWFriend;11 @interface JWFriendCell : UITableViewCell12 @property (nonatomic,strong) JWFriend *friendDatas;13 + (instancetype)cellWithTableView:(UITableView *)tableView;14 @end

 

 1 // 2 //  JWFriendCell.m 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import "JWFriendCell.h"10 #import "JWFriend.h"11 @implementation JWFriendCell12 //快速构造一个可重用的cee13 + (instancetype)cellWithTableView:(UITableView *)tableView {14     static NSString *resue = @"cell";15     JWFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:resue];16     if (!cell) {17         cell = [[self alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:resue];18     }19     return cell;20 }21 //重写set方法,给各子控件赋值22 - (void)setFriendDatas:(JWFriend *)friendDatas {23     _friendDatas = friendDatas;24     self.textLabel.text = friendDatas.name;25     self.detailTextLabel.text = friendDatas.intro;26     self.imageView.image = [UIImage imageNamed:friendDatas.icon];27     self.textLabel.textColor = friendDatas.isVip ? [UIColor redColor] : [UIColor blackColor];//如果是vip,那么呢称字体为红色28 }29 @end

 

 1 // 2 //  JWFriendHeaderView.h 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import <UIKit/UIKit.h>10 @class JWFriendGroup,JWFriendHeaderView;11 @protocol JWFriendHeaderViewDelegate <NSObject>12 @optional13 - (void)clickNameBtn:(JWFriendHeaderView *)headerView;14 15 @end16 @interface JWFriendHeaderView : UITableViewHeaderFooterView17 @property (nonatomic,strong) JWFriendGroup *friendGroup;18 @property (nonatomic,assign) id<JWFriendHeaderViewDelegate> delegate;19 + (instancetype)headerViewWithTableView:(UITableView *)tableView;20 @end

 

 1 // 2 //  JWFriendHeaderView.m 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import "JWFriendHeaderView.h"10 #import "JWFriendGroup.h"11 @interface JWFriendHeaderView ()12 @property (nonatomic,weak) UIButton *nameView;13 @property (nonatomic,weak) UILabel *countLabel;14 @end15 @implementation JWFriendHeaderView16 //快速构造一个可重用的组头17 + (instancetype)headerViewWithTableView:(UITableView *)tableView {18     static NSString *resue = @"head";//缓存池标识19     JWFriendHeaderView *headerView = [tableView dequeueReusableCellWithIdentifier:resue];20     if (!headerView) {21         headerView = [[self alloc] initWithReuseIdentifier:resue];22     }23     return headerView;24 }25 //重写方法,初始化控件26 - (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {27     if (self = [super initWithReuseIdentifier:reuseIdentifier]) {28         UIButton *nameBtn = [UIButton buttonWithType:UIButtonTypeCustom];29         [self.contentView addSubview:nameBtn];30         self.nameView = nameBtn;31         //按钮的一些属性的设置32         [nameBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];33         [nameBtn setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];34         [nameBtn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];35         [nameBtn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];36         nameBtn.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);//按钮内容的间距,左间距为1037         nameBtn.titleEdgeInsets =  UIEdgeInsetsMake(0, 10, 0, 0);//文字内容的间距,左间距为1038         nameBtn.imageView.contentMode = UIViewContentModeCenter;//不缩放按钮图片39         nameBtn.imageView.clipsToBounds = NO;//图片超出部分不裁剪40         nameBtn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;//设置左对齐41         [nameBtn addTarget:self action:@selector(nameClick) forControlEvents:UIControlEventTouchUpInside];//注册按钮点击事件42         43         UILabel *countLabel  = [[UILabel alloc] init];44         [self.contentView addSubview:countLabel];45         self.countLabel = countLabel;46         //文本标签的一些属性的设置47         countLabel.textAlignment = NSTextAlignmentRight;48         countLabel.font = [UIFont systemFontOfSize:14];49         countLabel.textColor = [UIColor grayColor];50     }51     return self;52 }53 //这个方法改变了组头的frame后就会调用,那么可以在这里设置frame了54 - (void)layoutSubviews {55     [super layoutSubviews];//记得必须先实现父类的该方法56     self.nameView.frame = self.bounds;57     CGFloat countX = self.bounds.size.width - 10 - 150;58     self.countLabel.frame = CGRectMake(countX, 0, 150, 44);59 }60 //点击组头按钮事件61 - (void)nameClick {62     self.friendGroup.expend = !self.friendGroup.isExpend;//获取组头是否展开状态63     [self expend];//调用封装的一个方法,如果展开,那么图片旋转90度,否则不展开64     if ([self.delegate respondsToSelector:@selector(clickNameBtn:)]) {//通知代理,点击了组头按钮65         [self.delegate clickNameBtn:self];66     }67 }68 //重写set方法,给各控件赋值69 - (void)setFriendGroup:(JWFriendGroup *)friendGroup {70     _friendGroup = friendGroup;//这句记得写,否则会造成没有内容显示71     [self.nameView setTitle:friendGroup.name forState:UIControlStateNormal];72     self.countLabel.text = [NSString stringWithFormat:@"%d/%lu",friendGroup.online,(unsigned long)friendGroup.friends.count];73     [self expend];//调用封装的一个方法,如果展开,那么图片旋转90度,否则不展开74 }75 //封装的方法,如果展开,那么图片旋转90度,否则旋转度为076 - (void)expend {77     CGFloat angle = self.friendGroup.isExpend ? M_PI_2 : 0;78     [UIView animateWithDuration:0.5 animations:^{79         self.nameView.imageView.transform = CGAffineTransformMakeRotation(angle);80     }];81 }82 @end

 

Controller:

 1 // 2 //  ViewController.m 3 //  12-24-FriendGroup 4 // 5 //  Created by xiaomoge on 14/12/24. 6 //  Copyright (c) 2014年 xiaomoge. All rights reserved. 7 // 8  9 #import "ViewController.h"10 #import "JWFriend.h"11 #import "JWFriendGroup.h"12 #import "JWFriendHeaderView.h"13 #import "JWFriendCell.h"14 @interface ViewController () <JWFriendHeaderViewDelegate>15 @property (nonatomic,strong) NSArray *friendGroup;16 @end17 18 @implementation ViewController19 #pragma mark - 隐藏状态栏20 - (BOOL)prefersStatusBarHidden {21     return YES;22 }23 #pragma mark - 懒加载24 - (NSArray *)friendGroup {25     if (!_friendGroup) {26         _friendGroup = [JWFriendGroup friendGroupList];27     }28     return _friendGroup;29 }30 - (void)viewDidLoad {31     [super viewDidLoad];32     //设置组头的高度33     self.tableView.sectionHeaderHeight = 44;34 }35 #pragma mark - tableViewDatasouce的方法36 //显示多少组数据37 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {38     return self.friendGroup.count;39 }40 //每组数据显示多少行数据41 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {42     return [self.friendGroup[section] isExpend ]?[self.friendGroup[section] friends].count : 0;//这里使用了三目运算符,主要是判断如果组头是展开的,那么显示行数据,否则显示为043 }44 //显示每个cell的内容45 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {46     JWFriendCell *cell = [JWFriendCell cellWithTableView:tableView];47     cell.friendDatas = [self.friendGroup[indexPath.section] friends][indexPath.row];48     return cell;49 }50 #pragma mark - JWFriendHeaderView的方法51 //显示组头view的内容52 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {53     JWFriendHeaderView *headerView = [JWFriendHeaderView headerViewWithTableView:tableView];54     headerView.friendGroup = self.friendGroup[section];55     headerView.delegate = self;56     headerView.tag = section;//把section赋值给组头的tag57     return headerView;58 }59 #pragma mark - JWFriendHeaderViewDelegate的方法60 - (void)clickNameBtn:(JWFriendHeaderView *)headerView {61     NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:headerView.tag];62     [self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationNone];//判断点击的是哪个组头,然后加载对应的数据63 }64 @end

 

 

UI基础--UITableView实现仿QQ好友列表页面