// 好友列表實(shí)現(xiàn)
UITableViewController, 設(shè)置起始控制器膏萧。
新建CZQQFriendsTableViewController 繼承自 UITableViewController
設(shè)置給storyBoard的Class北专。
// 模型嵌套刁赖。好友模型
#import <Foundation/Foundation.h>
@interface CZFriend :NSObject
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *intro;
@property (nonatomic, assign, getter = isVip) BOOL vip;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)friendWithDict:(NSDictionary *)dict;
@end
//----------------------
#import "CZFriend.h"
@implementation CZFriend
- (instancetype)initWithDict:(NSDictionary *)dict
{
if(self = [super init]){
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
+ (instancetype)friendWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end
// 分組模型
#import <Foundation/Foundation.h>
@interface CZGroup : NSObject
// 組名,在線人數(shù)并炮,當(dāng)前組的好友數(shù)據(jù)。
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int online;
@property (nonatomic, strong) NSArray *friends;
// 組的折疊狀態(tài)媚创。
@property (nonatomic, assign, getter=isVisible) BOOL *visible;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)groupWithDict:(NSDictionary *)dict;
@end
//----------------------
#import "CZGroup.h"
#import "CZFriend.h"
@implementation CZGroup
- (instancetype)initWithDict:(NSDictionary *)dict
{
if(self = [super init]){
[self setValuesForKeysWithDictionary:dict];
// self.friends中,字典數(shù)組轉(zhuǎn)模型數(shù)據(jù)
NSMutableArray *arrayModels = [NSMutableArray array];
for(NSDictionary *dict_sub in self.friends) {
CZFriend *model = [CZFriend friendWithDict:dict_sub];
[arrayModels addObject:model];
}
self.friends = arrayModels;
}
return self;
}
+ (instancetype)groupWithDict:(NSDictionary *)dict
{
return [[self alloc] initWithDict:dict];
}
@end
// 自定義Cell:CZFriendCell
// CZFriendCell.h
@class CZFriend;
@interface CZFriendCell : UITableViewCell
@property(nonatomic, strong) CZFriend *friendModel;
+ (instancetype)friendCellWithTableView:(UITableView *)tableView;
@end
//----------------------
// CZFriendCell.m
@implementation CZFriendCell
+ (instancetype)friendCellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"friend_cell";
CZFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if(cell == nil) {
cell = [[CZFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
return cell;
}
- (void)setFriendModel:(CZFriend *)friendModel
{
_friendModel = friendModel;
self.imageView.image = [UIImage imageNamed:friendModel.icon];
self.textLabel.text = friendModel.name;
self.detailTExtLabel.text = friendModel.intro;
// 判斷是否vip航瞭,將昵稱(chēng)顯示紅色或黑色
self.textLabel.text.textColor = friendModel.isVip
? [UIColor redColor]
: [UIColor blackColor];
}
- (void)awakeFromNib {
}
@end
// 自定義headerView诫硕。
// UITableViewHeaderFooterView
// 10.1新增代理協(xié)議
@class CZGroupHeaderView;
@protocol CZGroupHeaderViewDelegate <NSObject>
- (void)groupHeaderViewDidClickClickTitleButton:(CZGroupHeaderView *)groupHeaderVIew;
@end
@class CZGroup;
@interface CZGroupHeaderView : UITableViewHeaderFooterView
@property (nanotomic, strong) CZGroup *group;
+(instancetype)groupHeaderViewWithTableView:(UITableView *)tableView;
// 10.2新增代理屬性
@property (nanotomic, weak) id<CZGroupHeaderViewDelegate> delegate;
@end
//-----------------------
@interface CZGroupHeaderView ()
@property(nonatomic, weak) UIButton *btnGroupTitle;
@property(nonatomic, weak) UILabel *lblCount;
@end
@implementation CZGroupHeaderView
// 重寫(xiě)group的setGroup方法。
-(void)setGroup: (CZGroup *)group
{
_group = group;
[self.btnGroupTitle setTitle:group.name forState:UIControlStateNormal];
self.lblCount.text = [NSString stringWithFormat:@"%d / %d", group.online, group.friends.count];
// 設(shè)置按鈕中圖片的旋轉(zhuǎn)問(wèn)題刊侯。
if (self.group.isVisible) {
// 3.修改按鈕圖片章办,讓按鈕旋轉(zhuǎn)90度。
self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
} else { // 旋轉(zhuǎn)回到原來(lái)的位置
self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(0);
}
// 不要將設(shè)置frame的方法寫(xiě)在這里滨彻,因?yàn)榇颂帿@取的self的frame寬高信息都是0.
}
// 當(dāng)當(dāng)前控件的frame發(fā)生改變的時(shí)候藕届,調(diào)用。
- (void)layoutSubViews {
[super layoutSubViews];
// 設(shè)置按鈕的frame亭饵,設(shè)置labelframe
self.btnGroup.frame = self.bounds;
CGFloat lblW = 100;
CGFloat lblH = self.bounds.size.height;
CGFloat lblX = self.bounds.size.width -10 - lblW;
CGFloat lblY = 0;
self.lblCount.frame = CGRectMake(lblX, lblY, lblW, lblH);
}
// 封裝類(lèi)方法休偶,創(chuàng)建headerVIew
+ (instancetype)groupHeaderViewWithTableView:(UITableView *)tableView{
static NSString *ID = @"group_header_view";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];
if(headerView == nil) {
headerView = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:ID];
}
return headerView;
}
// 重寫(xiě)方法,創(chuàng)建headerView時(shí)辜羊,同時(shí)添加自定義的按鈕和label踏兜。
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
if(self = [super initWithReuseIdentifier:reuseIdentifier]) {
// 創(chuàng)建按鈕+label
UIButton *btnGroupTitle = [[UIButton alloc] init];
[self.contentView addSubview:btnGroupTitle];
self.btnGroupTitle = btnGroupTitle;
// 設(shè)置按鈕圖片(三角圖片,高亮背景圖)
[btnGroupTitle setImage:[UIImage iamgeNamed:@"header_arrow"] forState:UIControlStateNormal];
[btnGroupTitle setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
// 設(shè)置按鈕的點(diǎn)擊背景,2個(gè)模式Normal八秃,Highlighted
// [btnGroupTitle setBackgroundImage: forState:];
// 設(shè)置對(duì)齊方式, 間距
btnGroupTitle.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
btnGroupTitle.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
btnGroupTitle.titleEdgeInsets = UIEdgeInsetsMake(0, 5, 0, 0);
// 添加點(diǎn)擊事件
[btnGroupTitle addTarget:self action:@selector(btnGroupTitleClicked) forControlEvents:UIControlEventTouchUpInside];
// 設(shè)置按鈕的顯示模式
btnGroupTitle.imageView.contentMode = UIViewCOntentModeCenter;
btnGroupTitle.imageView.clipsToBounds = NO; // 不截取多余部分碱妆。
UILabel *lblCount = [[UILabel alloc] init]; // 好友數(shù)量顯示
[self.contentView addSubview:lblCount];
self.lblCount = lblCount;
}
return self;
}
// 組標(biāo)題按鈕的,點(diǎn)擊事件
- (void) btnGroupTitleClicked
{
// 1.設(shè)置組的展開(kāi)昔驱、折疊狀態(tài)
self.group.visible = !self.group.isVisible;
// 添加代理方法山橄,讓控制器遵守寫(xiě),實(shí)現(xiàn)代理方法舍悯。
// 10.3 使用代理,刷新TableView
if([self.delegate respondsToSelector:@selector(groupHeaderViewDidClickClickTitleButton:)]) {
// 調(diào)用代理方法,重新刷新
[self.delegate groupHeaderViewDidClickClickTitleButton:self];
}
}
// 當(dāng)1個(gè)新的headerView已經(jīng)加到某個(gè)父控件中的時(shí)候睡雇,執(zhí)行的回調(diào)方法萌衬。
// 處理三角形的旋轉(zhuǎn)。
- (void)didMoveToSuperview
{
if(self.group.isVisible) {
// 3.修改按鈕圖片它抱,讓按鈕旋轉(zhuǎn)90度秕豫。
self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(M_PI_2);
} else { // 旋轉(zhuǎn)回到原來(lái)的位置
self.btnGroupTitle.imageView.transform = CGAffineTransformMakeRotation(0);
}
}
@end
// 主控制器類(lèi),繼承自TableViewController
// CZQQFriendsTableViewController.h
@interface CZQQFriendsTableViewController
@end
//----------------------
#import "CZQQFriendsTableViewController.h"
// 類(lèi)拓展中观蓄,保存數(shù)據(jù)
@interface CZQQFriendsTableViewController () <CZGroupHeaderViewDelegate>
@property(nonatomic, strong) NSArray *groups;
@end
@implementation CZQQFriendsTableViewController
#pragma mark - ***懶加載數(shù)據(jù)***
- (NSArray *)groups
{
if(_groups == nil) {
NSSgring *path = [[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil];
NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
NSMutableArray *arrayModels = [NSMutableArray array];
for(NSDictionary *dict in arrayDict) {
CZGroup *model = [CZGroup groupWithDict:dict];
[arrayModels addObject:model];
}
_group = arrayModels;
}
return _groups;
}
#pragma mark - ***實(shí)現(xiàn)CZGroupHeaderViewDelegate代理方法***
- (void)groupHeaderViewDidClickTitleButton:(CZGroupHeaderView *)groupHeaderView
{
// 刷新tableView
// [self.tableView reloadData];
// 局部刷新混移,只刷新某個(gè)組。tag取到之前保存的組序號(hào)侮穿。
NSIndexSet *idxSet = [NSIndexSet indexSetWithIndex:groupHeaderView.tag];
[self.table reloadSections:idxSet withRowAnimation:UITableViewRowAnimationFade];
}
#pragma mark - ***實(shí)現(xiàn)數(shù)據(jù)源方法***
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.groups.count;
}
// self.group.visible = !self.group.isVisible;
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section
{
CZGroup *group = self.groups[section];
// 根據(jù)當(dāng)前組的狀態(tài)(是否展開(kāi))來(lái)設(shè)置不同的返回值歌径。
if(self.group.isVisible) {
return group.friends.count;
}
return 0;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 1. 獲取數(shù)據(jù)模型
CZGroup *group = self.groups[indexPath.section];
CZFriend *friend = group.friends[indexPath.row];
// 2. 創(chuàng)建單元格。
CZFriendCell *cell = [CZFriendCell friendCellWithTableView:tableView];
// 3.設(shè)置單元格數(shù)據(jù)
cell.friendModel = friend;
return cell; // 4.返回單元格
}
// 設(shè)置組標(biāo)題:自定義
// - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
// {
// CZGroup *group = self.groups[indexPath.section];
// return group.name
// }
// UITableViewHeaderFooterView 具有重用功能亲茅。UIView不能重用回铛。
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{ // 1.獲取模型狗准;2.創(chuàng)建View;3.設(shè)置數(shù)據(jù)
CZGroup *group = self.groups[section];
CZGroupHeaderView *headerView = [CZGroupHeaderView groupHeaderViewWithTableView:tableView];
headerView.tag = section; // 記下當(dāng)前第幾組茵肃。
headerView.group = group; // 設(shè)置數(shù)據(jù)
// 剛創(chuàng)建好的headerView腔长,它的frame都是0,因?yàn)檫@個(gè)headerView验残,我們沒(méi)為其frame賦值捞附。所以frame都是0.
// 但是程序運(yùn)行后,看到的headerView是有frame的您没。原因:在當(dāng)前方法中鸟召,將headerView返回以后,UITableView在執(zhí)行的時(shí)候紊婉,會(huì)用到headerView药版。當(dāng)headerView被用到,就必須將headerView添加到TableView中喻犁。當(dāng)添加到TableView中的時(shí)候槽片,UITableView內(nèi)部會(huì)根據(jù)設(shè)置來(lái)動(dòng)態(tài)為headerView的frame賦值。
// 也就是說(shuō)肢础,在TableView使用headerView的時(shí)候还栓,才會(huì)給headerView的frame賦值。
// 10.4 設(shè)置完數(shù)據(jù)后传轰,設(shè)置代理剩盒。
headerView.delegate = self;
return headerView; // 4.返回view
}
- (void)viewDidLoad {
[super viewDidLoad];
// 統(tǒng)一設(shè)置每組組標(biāo)題的高度
self.tableView.sectionHeaderHeight = 44;
}
@end
2023/06/02 周五