您的位置:首页 > 产品设计 > UI/UE

【iOS】UITableView中section的展开和收起

2017-10-14 08:44 465 查看
我们在做项目时,经常遇到UITableView需要展开与收起的情况,类似手机QQ的折叠,而且根据数据的不同判断有多少行需要展开与收起.之前做项目的时候也使用过,最近有时间整理,就把之前是怎么操作的记录下来。

首先,我们先说下思路:

思路:在写代码的时候我们可以很容易的写出cell和setion。但是系统并没有提供记录section状态的方法或是属性。我们需要点击某个section的时候收起和弹出cell。怎么做呢?只有是人为的给section增加一个标记了,每个section一个标记,section被点击了就把这个状态标记取反,根据这个标记来展开和收起cell

其中,设置方式又分为两种:

第一种:

设置cell的高度,高度为0了cell就收起了,高度大于0了cell就弹出

下面就直接贴代码了。

ViewController.m
#import "ViewController.h"
#import "SectionViewController.h"

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic,strong)UITableView *tableView;

@property (nonatomic,strong)NSMutableArray *sectionArray;
@property (nonatomic,strong)NSMutableArray *flagArray;

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
[self makeData];
_tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

/**
*  处理数据  _sectionArray里面存储数组
*/
- (void)makeData{
_sectionArray = [NSMutableArray array];
_flagArray  = [NSMutableArray array];
NSInteger num = 6;
for (int i = 0; i < num; i ++) {
NSMutableArray *rowArray = [NSMutableArray array];
for (int j = 0; j < arc4random()%20 + 1; j ++) {
[rowArray addObject:[NSString stringWithFormat:@"%d",j]];
}
[_sectionArray addObject:rowArray];
[_flagArray addObject:@"0"];
}
}
//设置组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return _sectionArray.count;
}
//设置行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSArray *arr = _sectionArray[section];
return arr.count;
}
//组头高度
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 44;
}
//cell的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if ([_flagArray[indexPath.section] isEqualToString:@"0"])
return 0;
else
return 44;
}
//组头
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
UILabel *sectionLabel = [[UILabel alloc] init];
sectionLabel.frame = CGRectMake(0, 0, self.view.frame.size.width, 444);
sectionLabel.textColor = [UIColor orangeColor];
sectionLabel.text = [NSString stringWithFormat:@"组%d",section];
sectionLabel.textAlignment = NSTextAlignmentCenter;
sectionLabel.tag = 100 + section;
sectionLabel.userInteractionEnabled = YES;
sectionLabel.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"itembg.png"]];

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(sectionClick:)];
[sectionLabel addGestureRecognizer:tap];

return sectionLabel;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identify = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identify];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identify];
}
cell.textLabel.text= [NSString stringWithFormat:@"第%d组的第%d个cell",indexPath.section,indexPath.row];
cell.clipsToBounds = YES;//这句话很重要,防止cell覆盖显示
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
SectionViewController *sVC = [[SectionViewController alloc] init];
sVC.rowLabelText = [NSString stringWithFormat:@"第%d组的第%d个cell",indexPath.section,indexPath.row];
[self presentViewController:sVC animated:YES completion:nil];
}
- (void)sectionClick:(UITapGestureRecognizer *)tap{
int index = tap.view.tag % 100;

NSMutableArray *indexArray = [[NSMutableArray alloc]init];
NSArray *arr = _sectionArray[index];
for (int i = 0; i < arr.count; i ++) {
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:index];
[indexArray addObject:path];
}
//展开
if ([_flagArray[index] isEqualToString:@"0"]) {
_flagArray[index] = @"1";
[_tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationBottom];  //使用下面注释的方法就 注释掉这一句
} else { //收起
_flagArray[index] = @"0";
[_tableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationTop]; //使用下面注释的方法就 注释掉这一句
}
//另一种刷新方式
//  NSRange range = NSMakeRange(index, 1);
//  NSIndexSet *sectionToReload = [NSIndexSet indexSetWithIndexesInRange:range];
//  [_tableView reloadSections:sectionToReload withRowAnimation:UITableViewRowAnimationAutomatic];
}
@end


附上代码的下载地址:Demo地址

第二种:

设置section数组的个数,数组个数为0了cell就收起了,数组个数大于0了cell就弹出

demo:

附上主要代码片段,仅提供思路参考:

1.设置数据源:

//设置属性
@property(nonatomic, strong) NSMutableArray* listArray;/**< 数组 */
@property(nonatomic, strong) NSMutableDictionary* foldInfoDic;/**< 存储开关字典 */

@property(nonatomic, strong) NSDictionary *topDic;
@property(nonatomic, strong) NSDictionary *orderDic;
@property(nonatomic, strong) NSDictionary *userDic;
@property(nonatomic, strong) NSDictionary *accountDic;
@property(nonatomic, strong) NSDictionary *paymentDic;
@property(nonatomic, strong) NSDictionary *bootomDic;

#pragma marl ---load lazing

-(NSDictionary *)topDic
{
if (!_topDic) {
_topDic = @{@"title":@"",@"data":@[@""]};
}
return _topDic;

}

-(NSDictionary *)orderDic
{
if (!_orderDic) {
_orderDic = @{@"title":@"订单信息",@"data":@[@"订单信息",@"收益",@"交易类型",@"支付币种",@"汇率",@"备注"]};
}
return _orderDic;

}
-(NSDictionary *)userDic{
if (!_userDic) {
_userDic = @{@"title":@"用户信息",@"data":@[@"用户名",@"联系方式"]};
}
return _userDic;
}
-(NSDictionary *)accountDic
{
if (!_accountDic) {
_accountDic = @{@"title":@"收款账户信息",@"data":@[@"联系方式",@"开户银行",@"开户名"]};
}
return _accountDic;
}
-(NSDictionary *)paymentDic
{

if (!_paymentDic) {
_paymentDic = @{@"title":@"汇款凭证",@"data":@[@""]};
}
return _paymentDic;
}
-(NSDictionary *)bootomDic
{
if (!_bootomDic) {
_bootomDic = @{@"title":@"",@"data":@[@"订单编号",@"下单时间"]};
}
return _bootomDic;

}
-(NSMutableArray *)listArray
{
if (!_listArray) {
_listArray = [NSMutableArray array];
}
return _listArray;

}
-(NSMutableDictionary *)foldInfoDic
{
if (!_foldInfoDic) {
_foldInfoDic = [NSMutableDictionary dictionary];
}
return _foldInfoDic;

}

2.根据需要加载需要的数据源,并设置记录是否展开的section对应de字典

[self.listArray addObject:self.topDic];
[self.listArray addObject:self.orderDic];
[self.listArray addObject:self.userDic];
[self.listArray addObject:self.accountDic];
//根据项目需要判断需要添加哪些section数据
if (self.orderType == FinancierAcceptarbitrateType || self.orderType == FinancierAcceptFinishType) {
[self.listArray addObject:self.paymentDic];
}else{
if (self.orderType == FinancierAcceptTradingType) {

}
}

[self.listArray addObject:self.bootomDic];
//设置section属性
for (int i=0; i<self.listArray.count; i++) {
NSDictionary *dic = self.listArray[i];
NSString *key = [NSString stringWithFormat:@"%d",i];
[self.foldInfoDic setObject:@"1" forKey:key];
}

设置tableView:
#pragma mark --- UITableViewDataSource and UITableViewDelegate Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

return self.listArray.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

NSDictionary *dic = self.listArray[section];
NSArray *cellArray = [NSArray arrayWithArray:dic[@"data"]];

NSString *key = [NSString stringWithFormat:@"%d",(int)section];
BOOL folded = [[self.foldInfoDic objectForKey:key] boolValue];
if (folded) {
return cellArray.count;
}else{
return 0;
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

if (indexPath.section == 0 ) {
static NSString *CellIdentifier = @"FinancierAcceptDetailTopCell";
FinancierAcceptDetailTopCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[FinancierAcceptDetailTopCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.orderType = self.orderType;

// cell.delegate = self;
cell.layer.masksToBounds = YES;

return cell;
}else{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.textColor = [UIColor grayColor];
cell.textLabel.font = [UIFont systemFontOfSize:15];
cell.detailTextLabel.textColor = [UIColor blackColor];
cell.detailTextLabel.font = [UIFont systemFontOfSize:15];
}

//清界面--
for (UIView *view in cell.subviews) {
if ([view isKindOfClass:[UIImageView class]]) {
[view removeFromSuperview];
}
if ([view isKindOfClass:[UILabel class]]) {
[view removeFromSuperview];
}
}

NSDictionary *dic = self.listArray[indexPath.section];
NSArray *cellArray = [NSArray arrayWithArray:dic[@"data"]];
NSString *title = [NSString stringWithFormat:@"%@",dic[@"title"]];
if ([title isEqualToString:@"汇款凭证"]) {

cell.textLabel.text = @"";
cell.detailTextLabel.text = @"";
_paymentImg = [[UIImageView alloc] initWithFrame:CGRectMake((mainWidth-255)/2, 15, 255, 160)];
[cell addSubview:_paymentImg];
//判断下imgView
_paymentImg.image = [UIImage imageNamed:@"A5_2_payment"];

}else{
cell.textLabel.text = cellArray[indexPath.row];
cell.detailTextLabel.text = [NSString stringWithFormat:@"test%ld-%ld",indexPath.section,indexPath.row];
}
cell.layer.masksToBounds = YES;
return cell;
}
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 0) {
if (self.orderType ==FinancierAcceptTradingType ||self.orderType ==FinancierAcceptCancelType) {
return 140;
}
return 104;
}
NSDictionary *dic = self.listArray[indexPath.section];
NSString *title = [NSString stringWithFormat:@"%@",dic[@"title"]];
if ([title isEqualToString:@"汇款凭证"]) {
return 190;
}

return 44;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
if (section == 0) {
return 0.01;
}else if (section == self.listArray.count-1)
{
return 0.01;
}
return 44;

}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 10;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

if (section == 0 || (section == self.listArray.count-1)) {
UIView *view = [[UIView alloc] init];
return view;
}else{
FinancierHeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"];
if (!headerView) {
headerView = [[FinancierHeaderView alloc] initWithReuseIdentifier:@"header"];
}
NSDictionary *dic = self.listArray[section];
NSString *title = [NSString stringWithFormat:@"%@",dic[@"title"]];
[headerView setFoldSectionHeaderViewWithTitle:title section:section canFold:YES];
headerView.delegate = self;
NSString *key = [NSString stringWithFormat:@"%d", (int)section];
BOOL folded = [[_foldInfoDic objectForKey:key] boolValue];
headerView.fold = folded;
return headerView;
}

}
- (void)foldHeaderInSection:(NSInteger)SectionHeader {
NSString *key = [NSString stringWithFormat:@"%d",(int)SectionHeader];
BOOL folded = [[_foldInfoDic objectForKey:key] boolValue];
NSString *fold = folded ? @"0" : @"1";
[self.foldInfoDic setObject:fold forKey:key];
// NSMutableIndexSet *set = [[NSMutableIndexSet alloc] initWithIndex:SectionHeader];
// [_tableView reloadSections:set withRowAnimation:UITableViewRowAnimationNone];
//刷整个section
NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:SectionHeader];
[self.tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];

//展开
// if (folded) {
// [_tableView reloadSections:set withRowAnimation:UITableViewRowAnimationBottom];
//
// } else { //收起
// [_tableView reloadSections:set withRowAnimation:UITableViewRowAnimationTop];
// }
}
其中,FinancierHeaderView自定义的tableHeaderView

FinancierHeaderView.h

#import <UIKit/UIKit.h>

@protocol FinancierHeaderViewCellDelegate <NSObject>
- (void)foldHeaderInSection:(NSInteger)SectionHeader;
@end

@interface FinancierHeaderView : UITableViewHeaderFooterView

@property(nonatomic,strong) UIImageView *rightImg;
@property(nonatomic,strong) UIView *headerView;
@property(nonatomic,strong) UIButton* rightBtn;
@property(nonatomic,strong) UILabel*titleLb;
@property(nonatomic,assign) NSInteger index;

@property(nonatomic,weak)id<FinancierHeaderViewCellDelegate> delegate;

@property(nonatomic, assign) BOOL fold;/**< 是否折叠 */
@property(nonatomic, assign) NSInteger section;/**< 选中的section */

- (void)setFoldSectionHeaderViewWithTitle:(NSString *)title section:(NSInteger)section canFold:(BOOL)canFold;

@end

FinancierHeaderView.m
#import "FinancierHeaderView.h"

@interface FinancierHeaderView()
{
BOOL _created;/**< 是否创建过 */
BOOL _canFold;/**< 是否可展开 */

}
@end

@implementation FinancierHeaderView

- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier{

self = [super initWithReuseIdentifier:reuseIdentifier];

if (self) {

// [self setUpUI];//_init表示初始化方法
}

return self;
}
- (void)setFoldSectionHeaderViewWithTitle:(NSString *)title section:(NSInteger)section canFold:(BOOL)canFold
{
if (!_created) {
[self setUpUI];
}
_titleLb.text = title;
_section = section;
_canFold = canFold;
if (canFold) {
_rightImg.hidden = NO;
} else {
_rightImg.hidden = YES;
}
}

- (void)setUpUI
{
_created = YES;

CGFloat space = 10;
_headerView = [[UIView alloc] init];
_headerView.backgroundColor = [UIColor whiteColor];
[self addSubview:_headerView];
[_headerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(0);
make.width.mas_equalTo(mainWidth);
make.height.mas_equalTo(44);
}];

_titleLb = [[UILabel alloc] init];
_titleLb.font = [UIFont systemFontOfSize:15];
[_headerView addSubview:_titleLb];
[_titleLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(space);
make.width.mas_equalTo(mainWidth-50);
make.height.mas_equalTo(44);
}];

_rightImg = [[UIImageView alloc] initWithFrame:CGRectMake(mainWidth-40, 17, 20, 10)];
_rightImg.image = [UIImage imageNamed:@"A5_up"];
[_headerView addSubview:_rightImg];
[_rightImg mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(17);
make.left.mas_equalTo(mainWidth-40);
make.width.mas_equalTo(20);
make.height.mas_equalTo(10);
}];

_rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];
_rightBtn.selected = YES;
[_rightBtn addTarget:self action:@selector(rightBtnClick:) forControlEvents:UIControlEventTouchUpInside ];
[_headerView addSubview:_rightBtn];
[_rightBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(0);
make.left.mas_equalTo(0);
make.width.mas_equalTo(mainWidth);
make.height.mas_equalTo(44);
}];

UIView *lineView = [[UIView alloc] init];
lineView.backgroundColor = [UIColor groupTableViewBackgroundColor];
[_headerView addSubview:lineView];
[lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(43.6);
make.left.mas_equalTo(0);
make.width.mas_equalTo(mainWidth);
make.height.mas_equalTo(0.4);
}];
}

- (void)rightBtnClick:(UIButton *)sender
{
if (_canFold) {
if ([self.delegate respondsToSelector:@selector(foldHeaderInSection:)]) {
[self.delegate foldHeaderInSection:_section];
}
}
}
- (void)setFold:(BOOL)fold {
_fold = fold;
if (fold) {
_rightImg.image = [UIImage imageNamed:@"A5_up"];
} else {
_rightImg.image = [UIImage imageNamed:@"A5_down"];
}
}

@end



OK,以后有空在整理下第二种方式的代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息