一、实现效果

           

二、实现代码

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:.f];
self.detailTextLabel.font=[UIFont systemFontOfSize:.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(, , , );
//设置按钮上文字距离小三角图片的距离
btn.titleEdgeInsets=UIEdgeInsetsMake(, , , );
//设置按钮上分组标题的文本颜色(默认是白色)
//[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=;
CGFloat labW=;
CGFloat labH=self.frame.size.height;
CGFloat labY=;
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 = ; } #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 ;
}
}
//每组每行的内容
-(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 ;
} #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;

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

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

    iOS开发UI篇—使用UItableview完成一个简单的QQ好友列表(一) 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableViewController // ...

  2. OS开发UI篇—使用UItableview完成一个简单的QQ好友列表

    本文转自:http://www.cnblogs.com/wendingding/p/3763330.html 一.项目结构和plist文件 二.实现代码 1.说明: 主控制器直接继承UITableVi ...

  3. iOS开发UI篇—实现UItableview控件数据刷新

    iOS开发UI篇—实现UItableview控件数据刷新 一.项目文件结构和plist文件 二.实现效果 1.说明:这是一个英雄展示界面,点击选中行,可以修改改行英雄的名称(完成数据刷新的操作). 运 ...

  4. iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建

    iOS开发UI篇—在UITableview的应用中使用动态单元格来完成app应用程序管理界面的搭建 一.实现效果 说明:该示例在storyboard中使用动态单元格来完成. 二.实现 1.项目文件结构 ...

  5. iOS开发UI篇—在UItableview中实现加载更多功能

    一.实现效果 点击加载更多按钮,出现一个加载图示,三秒钟后添加两条新的数据.                      二.实现代码和说明 当在页面(视图部分)点击加载更多按钮的时候,主页面(主控制器 ...

  6. iOS开发UI篇—CALayer简介

    iOS开发UI篇—CALayer简介   一.简单介绍 在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView. 其实 ...

  7. iOS开发UI篇—Button基础

    iOS开发UI篇—Button基础 一.简单说明 一般情况下,点击某个控件后,会做出相应反应的都是按钮 按钮的功能比较多,既能显示文字,又能显示图片,还能随时调整内部图片和文字的位置 二.按钮的三种状 ...

  8. ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局

    本文转自 :http://www.cnblogs.com/wendingding/p/3761730.html ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布 ...

  9. iOS开发UI篇—UITableview控件简单介绍

    iOS开发UI篇—UITableview控件简单介绍 一.基本介绍 在众多移动应⽤用中,能看到各式各样的表格数据 . 在iOS中,要实现表格数据展示,最常用的做法就是使用UITableView,UIT ...

随机推荐

  1. SD卡读写遇到的一些函数

    SD_SPI_ReadWriteByte(0XFF): 你的数据线写0xff,就是一直保持高,clk就有了8个,可以说只是发送的数据是0xff,这又不是SD的命令,但是它必须要靠控制器提供时钟才能工作 ...

  2. mssql手工注入及绕过术

      报错注入: - 例子:http://www.kfgtfcj.xxx.cn/lzygg/Zixun_show.aspx?id=1 [1]首先爆版本:http://www.kfgtfcj.xxx.cn ...

  3. POJ 2104 K-th Number(主席树——附讲解)

    Description You are working for Macrohard company in data structures department. After failing your ...

  4. 我去,徒弟半夜来电让写一个PHP短信验证(和群发)

    感觉很纳闷啊,,..好几天几乎通宵了,今晚本来以为有个早觉睡,居然2点多才打电话来让帮忙... 记得前段时间还有博友问过同类的问题.... 名字我就隐藏掉了,呵呵,, 我在网上随便找了一个提供相应接口 ...

  5. opencv的学习笔记3

    CMake是一个比make更高级的编译配置工具,它可以根据不同平台.不同的编译器,生成相应的Makefile或者vcproj项目.通过编写CMakeLists.txt,可以控制生成的Makefile, ...

  6. 数据库的Index Scan V.S. Rscan

    一直在做performance,但直到今天才完成了这个第一天应该完成的图,到底Index scan和Rscan的分界点在哪里?   如下图所示,很简单的一个查询,只是查询int,分别强制走索引和表扫描 ...

  7. 自定义view 画圆

    package com.exaple.day01rikao; import android.content.Context; import android.graphics.Canvas; impor ...

  8. core animation (转)

    iOS Core Animation 简明系列教程 看到无数的CA教程,都非常的难懂,各种事务各种图层关系看的人头大.自己就想用通俗的语言翻译给大家听,尽可能准确表达,如果哪里有问题,请您指出我会尽快 ...

  9. 关于treeview手动添加的方法

    1.首先判断有没有父节点,有父节点的,NEW一个父节点然后增加:没有父节点就选当前的节点 treeView2.Nodes.Add(newChildNode); 2.父节点的判断可以用leveL来判断 ...

  10. 报错:org.eclipse.swt.SWTError: No more handles at org.eclipse.swt.SWT.error(SWT.java:4517)

    在Mars.Kepler的版本裡,時常會出現以下錯誤導致eclipse無法進行運作 Error.log org.eclipse.swt.SWTError: No more handles     at ...