小編敲代碼實(shí)現(xiàn)項(xiàng)目功能時(shí)荣回,心中總會(huì)打上許多問號(hào)“ 遭贸?”,雖然項(xiàng)目的UI和功能都實(shí)現(xiàn)了心软,但總覺得自己的方法很low壕吹,沒有什么復(fù)用度和設(shè)計(jì)模式可言,處于低級(jí)階段删铃,離高新的目標(biāo)很是遙遠(yuǎn)6帷!猎唁!更不要說迎娶白富美了"~".......好了咒劲,扯了有點(diǎn)遠(yuǎn)了,言歸正傳:UITableView折疊效果(類似QQ聯(lián)系人的折疊)诫隅,在沒有看到大神博客的時(shí)候缎患,
我實(shí)現(xiàn)的套路如下:
1、使用Xib定制兩個(gè)Cell(一個(gè)標(biāo)題Cell阎肝,一個(gè)展開Cell)
2挤渔、折疊展開是通過改變tableView的section分區(qū)中cell的個(gè)數(shù),折疊時(shí)數(shù)量1风题,展開時(shí)數(shù) 量就有多個(gè)
3判导、兩個(gè)重要參數(shù):一個(gè)NSArray存儲(chǔ)內(nèi)容(后臺(tái)數(shù)據(jù)請(qǐng)求返回的)嫉父,
一個(gè)NSDictionary記錄“折疊展開”
4、改變“折疊”“展開狀態(tài)”眼刃,通過刷新整個(gè)tableIView展示
不足的是:
1绕辖、在cellForRow方法中要判斷是標(biāo)題Cell還是展開Cell
2、在cell的點(diǎn)擊方法中也是需要判斷是標(biāo)題Cell還是展開Cell
3擂红、刷新整個(gè)tableView仪际,消耗的資源比較大(當(dāng)然可以只是刷新某個(gè)section)
雖然實(shí)現(xiàn)的代碼量不多,邏輯也不復(fù)雜昵骤,但是要知道項(xiàng)目是會(huì)成長(zhǎng)的树碱,后續(xù)添加的功能需求只會(huì)越來越多,這就考驗(yàn)當(dāng)初設(shè)計(jì)時(shí):代碼的靈活度变秦、代碼的分工明不明細(xì)(影響代碼的可讀性)成榜、代碼的擴(kuò)展性等等,這就是我們經(jīng)潮拿担看到一些大神在實(shí)現(xiàn)一些簡(jiǎn)單功能的時(shí)候總會(huì)創(chuàng)建幾個(gè)分類赎婚,然后跳來跳去的,心中就疑惑就起來了.....
接下來談?wù)劥笊竦姆椒ǎ嫦驅(qū)ο蟮木幊趟枷耄?/h5>
1樱溉、依然是通過改變tableView的section分區(qū)中cell的個(gè)數(shù)挣输,不同的是折疊時(shí)為0,展開時(shí)是多個(gè)福贞,因?yàn)椴季种袠?biāo)題cell是在每個(gè)section的頭視圖顯示的(這樣在cellForRow中就不需要判斷)
2撩嚼、創(chuàng)建UITableViewHeaderFooterView的子類,自定義標(biāo)題內(nèi)容
3肚医、自定義cell,顯示展開后的cell
4向瓷、創(chuàng)建section模型肠套,存儲(chǔ)每組section的內(nèi)容
5、創(chuàng)建cell模型猖任,存儲(chǔ)展開后每個(gè)cell的內(nèi)容
6你稚、單獨(dú)刷新section
詳情請(qǐng)看代碼:
先看效果圖,有個(gè)概念
建立模型:
@interface SectionModel : NSObject
@property (nonatomic,assign) BOOL isExpand;
@property (nonatomic,strong) NSString *title;
@property (nonatomic,strong) NSArray *cellArray;
@end
@interface CellModel : NSObject
@property (nonatomic,strong) NSString *title;
@end
創(chuàng)建一個(gè)繼承于UITableViewHeaderFooterView的子類"SectionView"
@class SectionModel;
typedef void(^CallBackBlock)(BOOL);
@interface SectionView : UITableViewHeaderFooterView
@property (nonatomic,strong) SectionModel *model;
@property (nonatomic,strong) CallBackBlock block;
@end
.m文件
/* 在構(gòu)造方法中朱躺,創(chuàng)建UI*/
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithReuseIdentifier:reuseIdentifier]) {
CGFloat w = [UIScreen mainScreen].bounds.size.width;
self.arrowImage = [[UIImageView alloc]initWithFrame:CGRectMake(10, (44 - 8) / 2, 15, 8)];
self.arrowImage.image = [UIImage imageNamed:@"right.png"];
[self.contentView addSubview:self.arrowImage];
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0, 0, w, 44)];
[button addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:button];
self.titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(30, (44 - 20) / 2, w-20, 20)];
self.titleLabel.font = [UIFont systemFontOfSize:17];
self.titleLabel.textColor = [UIColor blackColor];
UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0, 43, w, 1)];
line.backgroundColor = [UIColor darkGrayColor];
[self.contentView addSubview:line];
[self.contentView addSubview:self.titleLabel];
self.contentView.backgroundColor = [UIColor yellowColor];
}
return self;
}
/*
1刁赖、通過懶加載,設(shè)置“箭頭”的方向
2长搀、通過頭視圖SectionView的點(diǎn)擊宇弛,改變“箭頭”的方向
3、通過點(diǎn)擊SectionView源请,回調(diào)block進(jìn)行section刷新
*/
- (void)setModel:(SectionModel *)model{
if (_model != model) {
_model = model;
}
self.titleLabel.text = model.title;
if (model.isExpand) { //展開
self.arrowImage.transform = CGAffineTransformIdentity;
}else{
self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
}
}
- (void)btnClick:(UIButton *)sender{
self.model.isExpand = ! self.model.isExpand;
if (self.model.isExpand) {
self.arrowImage.transform = CGAffineTransformIdentity;
}else{
self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
}
if (self.block) {
self.block(self.model.isExpand);
}
}
tableView 的配置
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic,strong) UITableView *tableView;
@property (nonatomic,strong) NSMutableArray *sectionData;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:self.tableView];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cellid"];
[self.tableView registerClass:[SectionView class] forHeaderFooterViewReuseIdentifier:@"header"];
}
//懶加載
- (NSMutableArray *)sectionData{
if (_sectionData == nil) {
_sectionData = [[NSMutableArray alloc]init];
for (int i=0; i<20; i++) {
SectionModel *model = [[SectionModel alloc]init];
model.title = [NSString stringWithFormat:@"%d",i];
model.isExpand = NO;
NSMutableArray *array = [[NSMutableArray alloc]init];
for (int j=0; j<10; j++) {
CellModel *cell = [[CellModel alloc]init];
cell.title = [NSString stringWithFormat:@"LivenCell==Section:%d,Row:%d",i,j];
[array addObject:cell];
}
model.cellArray = array;
[_sectionData addObject:model];
}
}
return _sectionData;
}
#pragma mark - tableView delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.sectionData.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
SectionModel *model = _sectionData[section];
return model.isExpand?model.cellArray.count:0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellid"];
SectionModel *section = _sectionData[indexPath.section];
CellModel *model = section.cellArray[indexPath.row];
cell.textLabel.text = model.title;
return cell;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
SectionView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"];
SectionModel *model = _sectionData[section];
view.model = model;
//更變了section的cell數(shù)量枪芒,所以要刷新
view.block = ^(BOOL isExpanded){
[tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
};
return view;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 44;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 44;
}
整體的內(nèi)容就這么多彻况,這個(gè)Demo真的不錯(cuò),覺得好的自己多敲幾遍舅踪,最后必須感謝“標(biāo)哥”對(duì)我的啟發(fā)