前言:tableView的折叠效果在很多场景上都会使用,类似QQ联系人;下面我们通过对数据模型灵活运用来实现这一功能
设计思路:
- 定义数据模型结构
- 使用sectionHeader为一级分类,tableViewCell为二级分类
- 字典存储折叠标记(也可以在模型中添加相关标记来实现)
实现思路:
1.数据模型定义:
@class RoomVRecordDetailsModel;
@interface RoomVRecordModel : BaseModel
/**
开启时间
*/
@property(nonatomic, assign)NSTimeInterval time;
/**
投票名称
*/
@property(nonatomic, copy)NSString * voteName;
/**
总票数
*/
@property(nonatomic, assign)int count;
@property(nonatomic, strong)NSArray <RoomVRecordDetailsModel *> *vote;
@end
#pragma mark -- 展开之后的子模型
@interface RoomVRecordDetailsModel : BaseModel
/**
id
*/
@property(nonatomic, assign)int64_t PlayerId;
/**
昵称
*/
@property(nonatomic, copy)NSString * nickName;
/**
头像
*/
@property(nonatomic, copy)NSString * icon;
/**
票数
*/
@property(nonatomic, assign)NSInteger Vote;
@end
2.tableView代理实现:
#pragma mark -- UITableViewDelegate
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.listArray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSNumber *isCheck = [self.cacheDict objectForKey:@(section)];
if (isCheck.boolValue) {
RoomVRecordModel * model;
if (section < self.listArray.count) {
model = self.listArray[section];
}
return model.vote.count+1; //这里的+1根据需求来定夺,楼主这里+1是因为功能中,展开的子模型有个类似表头的cell
}else {
return 0;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 50;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return 40;
}
return 50;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
static NSString *identifier2 = @"RoomVoteRecordFormCell";
RoomVoteRecordFormCell * formCell = [tableView dequeueReusableCellWithIdentifier:identifier2 forIndexPath:indexPath];
return formCell;
}
static NSString *identifier = @"RoomVoteRecordCell";
RoomVoteRecordCell *cell=[tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
if (indexPath.section < self.listArray.count) {
RoomVRecordModel * model = self.listArray[indexPath.section];
if (indexPath.row <= model.vote.count) {
RoomVRecordDetailsModel * dModel = model.vote[indexPath.row-1];
cell.model = dModel;
}
}
return cell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *identifier = @"RoomVoteHeaderView";
RoomVoteHeaderView * headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:identifier];
if (!headerView) {
headerView = [[RoomVoteHeaderView alloc] initWithReuseIdentifier:identifier];
}
NSNumber *isSelected = [self.cacheDict objectForKey:@(section)];
headerView.selected = isSelected.boolValue;
if (section < self.listArray.count) {
RoomVRecordModel * model = self.listArray[section];
headerView.model = model;
}
[headerView setDidClickHeaderViewBlock:^(RoomVoteHeaderView *header) {
NSNumber *isCheck = [self.cacheDict objectForKey:@(section)];
if (isCheck.boolValue) {
[self.cacheDict setObject:@(NO) forKey:@(section)];
}else {
[self.cacheDict setObject:@(YES) forKey:@(section)];
}
// [self.tableView reloadData];
[tableView reloadSections:[[NSIndexSet alloc] initWithIndex:section] withRowAnimation:UITableViewRowAnimationNone];
}];
return headerView;
}
3.关于字典存储折叠标记:这里添加了一个NSMutableDictionary类型的cacheDict,使用方式已经在上面的tableView的代理方法中体现出来,这样做的好处是在下拉刷新或者上拉加载过程中,都能保留原来用户的折叠记忆情况,提高用户体验;
-(NSMutableDictionary *)cacheDict {
if (!_cacheDict) {
_cacheDict = [NSMutableDictionary dictionary];
}
return _cacheDict;
}
注意事项:
在简单写完这些代码之后,发现在滑动或者折叠的时候,页面会出现数据刷新不流畅问题,这里通过分析可能与tableView的某个设置/配置有关,通过设置section的预估行高则可以完美解决这个问题,self.tableView.estimatedSectionHeaderHeight = 50;使tableView变得更流畅;