iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)

it2022-05-05  75

iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(二)

一、实现效果

 

二、实现代码

1.数据模型部分

 YYQQGroupModel.h文件

// // YYQQGroupModel.h // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import <Foundation/Foundation.h> @interface YYQQGroupModel : NSObject /** * 名称属性 */ @property(nonatomic,copy)NSString *name; /** * 是否在线 */ @property(nonatomic,copy)NSString *online; /** * 好友列表 */ @property(nonatomic,strong)NSArray *friends; //记录当前组是否要打开 @property(nonatomic,assign,getter = isOpen)BOOL open; -(instancetype)initWithDict:(NSDictionary *)dict; +(instancetype) qqGroupModelWithDict:(NSDictionary *)dict; @end

YYQQGroupModel.m文件

// // YYQQGroupModel.m // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYQQGroupModel.h" #import "YYFriendsModel.h" @implementation YYQQGroupModel -(instancetype)initWithDict:(NSDictionary *)dict { if (self=[super init]) { //将字典转换为模型 [self setValuesForKeysWithDictionary:dict]; //定义一个数组来保存转换后的模型 NSMutableArray *models=[NSMutableArray arrayWithCapacity:self.friends.count]; for (NSDictionary *dict in self.friends) { YYFriendsModel *friends=[YYFriendsModel friendsWithDict:dict]; [models addObject:friends]; } _friends=[models copy]; } return self; } +(instancetype)qqGroupModelWithDict:(NSDictionary *)dict { return [[self alloc]initWithDict:dict]; } @end

YYFriendsModel.h文件

// // YYFriendsModel.h // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import <Foundation/Foundation.h> @interface YYFriendsModel : NSObject /** * 每个好友的名称 */ @property(nonatomic,copy)NSString *name; /** *每个好友的头像 */ @property(nonatomic,copy)NSString *icon; /** * 每个好友的个性签名 */ @property(nonatomic,copy)NSString *intro; /** * 该好友是否是vip */ @property(nonatomic,assign,getter = isVip)BOOL vip; -(instancetype)initWithDict:(NSDictionary *)dict; +(instancetype)friendsWithDict:(NSDictionary *)dict; @end

YYFriendsModel.m文件

// // YYFriendsModel.m // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYFriendsModel.h" @implementation YYFriendsModel -(instancetype)initWithDict:(NSDictionary *)dict { if (self=[super init]) { [self setValuesForKeysWithDictionary:dict]; } return self; } +(instancetype)friendsWithDict:(NSDictionary *)dict { return [[self alloc]initWithDict:dict]; } @end

2.视图部分

YYfriendCell.h文件

// // YYfriendCell.h // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import <UIKit/UIKit.h> @class YYFriendsModel; @interface YYfriendCell : UITableViewCell @property(nonatomic,strong)YYFriendsModel *friends; +(instancetype)cellWithTableview:(UITableView *)tableView; @end

YYfriendCell.m文件

// // YYfriendCell.m // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYfriendCell.h" #import "YYFriendsModel.h" //私有扩展 @interface YYfriendCell() @end @implementation YYfriendCell +(YYfriendCell *)cellWithTableview:(UITableView *)tableView { static NSString *identifier=@"qq"; YYfriendCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier]; if (cell==nil) { //这里使用系统自带的样式 cell=[[YYfriendCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier]; NSLog(@"创建一个cell"); } return cell; } -(void)setFriends:(YYFriendsModel *)friends { _friends=friends; //1.设置头像 self.imageView.image=[UIImage imageNamed:_friends.icon]; //2.设置昵称 self.textLabel.text=_friends.name; //3.设置简介 self.detailTextLabel.text=_friends.intro; //判断是否是会员 /** * 这里有个注意点,如果不写else设置为黑色,会怎么样? */ if (_friends.isVip) { [self.textLabel setTextColor:[UIColor redColor]]; }else { [self.textLabel setTextColor:[UIColor blackColor]]; } //调整字体的大小 self.textLabel.font=[UIFont systemFontOfSize:15.f]; self.detailTextLabel.font=[UIFont systemFontOfSize:10.f]; } @end

YYHeaderView.h文件

// // YYHeaderView.h // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-6-1. // Copyright (c) 2014年 itcase. All rights reserved. // #import <UIKit/UIKit.h> @class YYQQGroupModel,YYHeaderView; //商量一个协议 @protocol YYHeaderViewDelegate <NSObject> -(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView; @end @interface YYHeaderView : UITableViewHeaderFooterView @property(nonatomic,strong)YYQQGroupModel *group; //提供一个类方法,创建一个头部视图 +(instancetype)headerWithTableView:(UITableView *)tableView; //delegate遵守YYHeaderViewDelegate这个协议,可以使用协议中的方法 @property(nonatomic,weak)id<YYHeaderViewDelegate> delegate; @end

YYHeaderView.m文件

// // YYHeaderView.m // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-6-1. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYHeaderView.h" #import "YYQQGroupModel.h" @interface YYHeaderView() @property(nonatomic,strong)UIButton *btn; @property(nonatomic,strong)UILabel *lab; @end @implementation YYHeaderView //创建一个自定义的头部分组视图 +(instancetype)headerWithTableView:(UITableView *)tableView { static NSString *indentifier=@"header"; //先到缓存池中去取数据 YYHeaderView *headerview=[tableView dequeueReusableCellWithIdentifier:indentifier]; //如果没有,则自己创建 if (headerview==nil) { headerview=[[YYHeaderView alloc]initWithReuseIdentifier:indentifier]; } //返回一个头部视图 return headerview; } #warning 注意在构造方法中为控件设置的frame是无效的 -(id)initWithReuseIdentifier:(NSString *)reuseIdentifier { //初始化父类中的构造方法 if (self=[super initWithReuseIdentifier:reuseIdentifier]) { //创建一个按钮 UIButton *btn=[UIButton buttonWithType:UIButtonTypeCustom]; //设置按钮的属性 //设置普通状态下按钮的背景图片 [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal]; //设置高亮状态下按钮的背景图片 [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted]; //设置按钮上的小三角图片 [btn setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal]; //设置按钮上信息的对其方式为左对齐 btn.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft; //设置小三角图片的内边距 btn.contentEdgeInsets=UIEdgeInsetsMake(0, 20, 0, 0); //设置按钮上文字距离小三角图片的距离 btn.titleEdgeInsets=UIEdgeInsetsMake(0, 20, 0, 0); //设置按钮上分组标题的文本颜色(默认是白色) //[btn setTintColor:[UIColor blackColor]]; [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; //添加按钮的点击事件 [btn addTarget:self action:@selector(btnOnclick:) forControlEvents:UIControlEventTouchUpInside]; // 设置btn中的图片不填充整个imageview btn.imageView.contentMode = UIViewContentModeCenter; // 超出范围的图片不要剪切 // btn.imageView.clipsToBounds = NO; btn.imageView.layer.masksToBounds = NO; //把按钮添加到视图 [self addSubview:btn]; self.btn=btn; //创建一个lab UILabel *lab=[[UILabel alloc]init]; //设置在线人数的对齐方式为右对齐 lab.textAlignment=NSTextAlignmentRight; //设置在线人数的文本颜色为灰色 lab.textColor=[UIColor grayColor]; [self addSubview:lab]; self.lab=lab; } return self; } -(void)btnOnclick:(UIButton *)btn { NSLog(@"按钮被点击了"); //修改模型的isopen属性 //1.修改模型数据 self.group.open=!self.group.isOpen; //2.刷新表格 //(刷新表格的功能由控制器完成,在这里可以设置一个代理),当按钮被点击的时候,就通知代理对表格进行刷新 //通知代理 if ([self.delegate respondsToSelector:@selector(headerViewDidClickHeaderView:)]) { [self.delegate headerViewDidClickHeaderView:self]; } } //当控件的frame值改变时,会自动调用该方法,故可以在该方法中设置控件的frame; -(void)layoutSubviews { #warning 一定不要忘记调用父类的方法 [super layoutSubviews]; //设置按钮的frame和头部视图一样大小 self.btn.frame=self.bounds; //设置lab的frame CGFloat padding=20; CGFloat labW=50; CGFloat labH=self.frame.size.height; CGFloat labY=0; CGFloat labX=self.frame.size.width-padding-labW; self.lab.frame=CGRectMake(labX, labY, labW, labH); } #pragma mark - 当一个控件被添加到其它视图上的时候会调用以下方法 // 已经被添加到父视图上的时候会调用 - (void)didMoveToSuperview { NSLog(@"已经添加到视图了"); // 在这个方法中就快要拿到最新的被添加到tableview上的头部视图修改它的图片 if (self.group.isOpen) { //让小三角图片向下旋转 self.btn.imageView.transform = CGAffineTransformMakeRotation(M_PI_2); } } // 即将被添加到父视图上的时候会调用 - (void)willMoveToSuperview:(UIView *)newSuperview { NSLog(@"将要添加到视图了"); } //重写get方法,设置数据 -(void)setGroup:(YYQQGroupModel *)group { _group=group; //设置分组标题 //self.btn.titleLabel.text=_group.name; #warning 请注意在设置按钮的文本时,一定要设置按钮的状态,像上面这样设置不会显示 [self.btn setTitle:_group.name forState:UIControlStateNormal]; NSLog(@"%@",self.btn.titleLabel.text); //设置在线人数 self.lab.text=[NSString stringWithFormat:@"%@/%d",_group.online,_group.friends.count]; } @end

3.控制器部分

YYViewController.h文件

// // YYViewController.h // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import <UIKit/UIKit.h> @interface YYViewController : UITableViewController @end

YYViewController.m文件

// // YYViewController.m // 02-QQ好友列表(基本数据的加载) // // Created by apple on 14-5-31. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "YYQQGroupModel.h" #import "YYfriendCell.h" #import "YYFriendsModel.h" #import "YYHeaderView.h" @interface YYViewController ()<YYHeaderViewDelegate> /** * 用来保存所有的分组数据 */ @property(nonatomic,strong)NSArray *groupFriends; @end @implementation YYViewController #pragma mark-懒加载 //1.先拿到数据,实现懒加载 -(NSArray *)groupFriends { if (_groupFriends==nil) { NSString *fullpath=[[NSBundle mainBundle]pathForResource:@"friends.plist" ofType:nil]; NSArray *arrayM=[NSArray arrayWithContentsOfFile:fullpath]; NSMutableArray *models=[NSMutableArray arrayWithCapacity:arrayM.count]; for (NSDictionary *dict in arrayM) { YYQQGroupModel *group=[YYQQGroupModel qqGroupModelWithDict:dict]; [models addObject:group]; } _groupFriends=[models copy]; } return _groupFriends; } - (void)viewDidLoad { [super viewDidLoad]; self.tableView.sectionHeaderHeight = 100; } #pragma mark- 设置数据源 //返回多少组 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return self.groupFriends.count; } //每组返回多少行 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // //取出对应的组模型 YYQQGroupModel *group=self.groupFriends[section]; // //返回对应组中的好友数 // return group.friends.count; //在这里进行判断,如果该组收拢,那就返回0行,如果该组打开,就返回实际的行数 // if (group.isOpen) { // return group.friends.count; // }else // { // return 0; // } if (group.isOpen) { // 代表要展开 return group.friends.count; }else { // 代表要合拢 return 0; } } //每组每行的内容 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //1.创建cell YYfriendCell *cell=[YYfriendCell cellWithTableview:tableView]; //2.设置cell YYQQGroupModel *group=self.groupFriends[indexPath.section]; YYFriendsModel *friends=group.friends[indexPath.row]; cell.friends=friends; //3.返回一个cell return cell; } #pragma mark - 代理方法 // 当一个分组标题进入视野的时候就会调用该方法 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { // // 1.创建头部视图 // UIView *view = [[UIView alloc] init]; // view.backgroundColor = [UIColor grayColor]; // // 2.返回头部视图 // return view; //创建自定义的头部视图 YYHeaderView *headerview=[YYHeaderView headerWithTableView:tableView]; //设置当前控制器为代理 headerview.delegate=self; //设置头部视图的数据 YYQQGroupModel *groupmodel=self.groupFriends[section]; headerview.group=groupmodel; //返回头部视图 return headerview; } #pragma mark - YYHeaderViewDelegate -(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView { //重新调用数据源的方法刷新数据 [self.tableView reloadData]; } //设置分组头部标题的高度 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 30; } #pragma mark 隐藏状态栏 -(BOOL)prefersStatusBarHidden { return YES; } @end

三、代码说明

1.项目文件结构

 

2.注意点

(1)调整字体的大小:    self.textLabel.font=[UIFont systemFontOfSize:15.f];

(2)-(void)layoutSubviews方法。该方法在控件的frame被改变的时候就会调用,这个方法一般用于调整子控件的位置,注意一定要调用[super layoutSubviews];

(3)但凡在init方法中获取到的frame都是0;

(4)如果控件不显示,有以下一些排错方法

a.frame为空(没有设置frame) b.hidden是否为YES c.alpha<=0.1(透明度) d.没有添加到父控件中 e.查看父控件以上几点

(5)请注意在设置按钮的文本时,一定要设置按钮的状态

正确:[self.btn setTitle:_group.name forState:UIControlStateNormal]; 错误: self.btn.titleLabel.text=_group.name;

(6)调用构造方法时,一定要先初始化父类的方法,先判断,再进行自己属性的初始化

self=[super initWithReuseIdentifier:reuseIdentifier] if(self) { …… } (7)当一个控件被添加到其它视图上的时候会调用以下方法

1) 已经被添加到父视图上的时候会调用- (void)didMoveToSuperview

2) 即将被添加到父视图上的时候会调用- (void)willMoveToSuperview:(UIView *)newSuperview

(8)图片填充知识

   1)设置btn中的图片不填充整个imageview btn.imageView.contentMode = UIViewContentModeCenter;

   2)超出范围的图片不要剪切

  //btn.imageView.clipsToBounds = NO;

  btn.imageView.layer.masksToBounds = NO;

四、补充(代理)

设置代理的几个步骤 (1)如果一个视图中的某个按钮被点击了,这个时候需要去主控制器中刷新数据。有一种做法是,让这个视图拥有控制器这个属性,然后当按钮被点击的时候去利用该属性去做刷新数据的操作。另一种做法是把控制器设置为这个视图的代理,当视图中的某个按钮被点击的时候,通知它的代理(主控制器)去干刷新数据这件事。 (2)要成为代理是由条件的,有以下几个步骤 1).双方约定一个协议(代理协议,注意命名规范),在视图中自定义一个协议,协议中提供一个方法。

@protocol YYHeaderViewDelegate <NSObject>

-(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView;

@end

2).在视图中添加一个id类型的属性变量,任何人只要遵守了约定协议的都可以成为它的代理。

//delegate遵守YYHeaderViewDelegate这个协议,可以使用协议中的方法

@property(nonatomic,weak)id<YYHeaderViewDelegate> delegate;

3).在控制器中,遵守自定义的代理协议,就可以使用代理提供的方法,在这个方法中对数据进行刷新。

@interface YYViewController ()<YYHeaderViewDelegate>

-(void)headerViewDidClickHeaderView:(YYHeaderView *)headerView

{

    [self.tableView reloadData];

}

4).把控制器设置作为按钮点击事件的代理。

headerview.delegate=self;

转载于:https://www.cnblogs.com/yipingios/p/5549773.html

相关资源:各显卡算力对照表!

最新回复(0)