我实现的套路如下:
1、使用Xib定制两个Cell(一个标题Cell,一个展开Cell)2、折叠展开是通过改变tableView的section分区中cell的个数,折叠时数量1,展开时数 量就有多个3、两个重要参数:一个NSArray存储内容(后台数据请求返回的), 一个NSDictionary记录“折叠展开”4、改变“折叠”“展开状态”,通过刷新整个tableIView展示
不足的是:
1、在cellForRow方法中要判断是标题Cell还是展开Cell
2、在cell的点击方法中也是需要判断是标题Cell还是展开Cell
3、刷新整个tableView,消耗的资源比较大(当然可以只是刷新某个section)
虽然实现的代码量不多,逻辑也不复杂,但是要知道项目是会成长的,后续添加的功能需求只会越来越多,这就考验当初设计时:代码的灵活度、代码的分工明不明细(影响代码的可读性)、代码的扩展性等等,这就是我们经常看到一些大神在实现一些简单功能的时候总会创建几个分类,然后跳来跳去的,心中就疑惑就起来了.....
接下来谈谈大神的方法(面向对象的编程思想)
1、依然是通过改变tableView的section分区中cell的个数,不同的是折叠时为0,展开时是多个,因为布局中标题cell是在每个section的头视图显示的(这样在cellForRow中就不需要判断)
2、创建UITableViewHeaderFooterView的子类,自定义标题内容
3、自定义cell,显示展开后的cell
4、创建section模型,存储每组section的内容
5、创建cell模型,存储展开后每个cell的内容
6、单独刷新section
详情请看代码:
先看效果图,有个概念
spring.gif
建立模型:
@interfaceSectionModel: NSObject
@property(nonatomic,assign) BOOL isExpand;
@property(nonatomic,strong) NSString *title;@property(nonatomic,strong)NSArray *cellArray;
@end
@interfaceCellModel: NSObject
@property(nonatomic,strong) NSString *title;
@end
创建一个继承于UITableViewHeaderFooterView的子类"SectionView"
@classSectionModel;
typedefvoid(^CallBackBlock)(BOOL);
@interfaceSectionView:UITableViewHeaderFooterView
@property(nonatomic,strong) SectionModel *model;
@property(nonatomic,strong) CallBackBlock block;
@end
.m文件
/*
在构造方法中,创建UI
*/
- (instancetype)initWithReuseIdentifier:(NSString*)reuseIdentifier{if(self= [superinitWithReuseIdentifier:reuseIdentifier]) {CGFloatw = [UIScreenmainScreen].bounds.size.width;self.arrowImage = [[UIImageViewalloc]initWithFrame:CGRectMake(10, (44-8) /2,15,8)];self.arrowImage.image = [UIImageimageNamed:@"right.png"]; [self.contentView addSubview:self.arrowImage];UIButton*button = [[UIButtonalloc]initWithFrame:CGRectMake(0,0, w,44)]; [button addTarget:selfaction:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside]; [self.contentView addSubview:button];self.titleLabel = [[UILabelalloc]initWithFrame:CGRectMake(30, (44-20) /2, w-20,20)];self.titleLabel.font = [UIFontsystemFontOfSize:17];self.titleLabel.textColor = [UIColorblackColor];UIView*line = [[UIViewalloc]initWithFrame:CGRectMake(0,43, w,1)]; line.backgroundColor = [UIColordarkGrayColor]; [self.contentView addSubview:line]; [self.contentView addSubview:self.titleLabel];self.contentView.backgroundColor = [UIColoryellowColor]; }returnself;}
/*
1、通过懒加载,设置“箭头”的方向
2、通过头视图SectionView的点击,改变“箭头”的方向
3、通过点击SectionView,回调block进行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 的配置
@interfaceViewController()@property(nonatomic,strong)UITableView*tableView;@property(nonatomic,strong)NSMutableArray*sectionData;@end@implementationViewController- (void)viewDidLoad { [superviewDidLoad];self.tableView = [[UITableViewalloc]initWithFrame:self.view.frame style:UITableViewStylePlain];self.tableView.delegate =self;self.tableView.dataSource =self; [self.view addSubview:self.tableView]; [self.tableView registerClass:[UITableViewCellclass] forCellReuseIdentifier:@"cellid"]; [self.tableView registerClass:[SectionViewclass] forHeaderFooterViewReuseIdentifier:@"header"];}//懒加载- (NSMutableArray*)sectionData{if(_sectionData ==nil) { _sectionData = [[NSMutableArrayalloc]init];for(inti=0; i<20; i++) { SectionModel *model = [[SectionModel alloc]init]; model.title = [NSStringstringWithFormat:@"%d",i]; model.isExpand =NO;NSMutableArray*array = [[NSMutableArrayalloc]init];for(intj=0; j<10; j++) { CellModel *cell = [[CellModel alloc]init]; cell.title = [NSStringstringWithFormat:@"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{returnself.sectionData.count;}- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{ SectionModel *model = _sectionData[section];returnmodel.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;returncell;}- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section{ SectionView *view = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"]; SectionModel *model = _sectionData[section]; view.model = model;//更变了section的cell数量,所以要刷新view.block = ^(BOOLisExpanded){ [tableView reloadSections:[NSIndexSetindexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade]; };returnview;}- (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{return44;}- (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section{return44;}