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

我们在做项目时,经常遇到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,以后有空在整理下第二种方式的代码

猜你喜欢

转载自blog.csdn.net/baidu_25743639/article/details/78231880