首页 >iOS开发

UITableview 优雅的展开与收回

2017-04-18 09:20 编辑: suiling 分类:iOS开发 来源:mark666

原文

最近为项目的功能需求准备着,有一个很简单点击展开与收缩的功能需求,以前Swift中写过一个类似的功能,但是个人觉得不是特别好,当时就因为cell的复用导致了bug,并且这个需求是一直OC维护的项目,所以还是打算重写一个,现将项目中这个功能模块抽出来,与有相关需求的朋友分享一下。
首先上一下效果图:

1256700-c8de1c12bfe31e0a.gif

效果图

1.首先说一下这个效果的思路:主要是通过维护一个模型来构建通过UITableviewCell 的列表

1256700-4c0825d0967eceff.png

可维护的模型

本文主要的模型如上,并且这个模型可扩展性非常强,举个简单的例子的,DDSectionModel这个模型维护的是UITableViewHeaderFooterView,你可以将HeaderFooterView自定义为任何符合你需求的view;当然DDCellModel这个模型维护的是来维护cell,你可以定义cell来满足你的需求.

在DDSectionModel这个模型中有一个加载数据源的方法,当然你可以将此方法单独定一个类或者定义一个协议去加载数据来降低耦合度,本文采用构建plist来当做数据源:

QQ截图20170418092155.png

headerList.plist

2.loadData:(void(^)(NSArray *models))finished 方法的实现,可根据个人需求来构建模型

+ (void)loadData:(void(^)(NSArray *models))finished{


    NSMutableArray *dataArr = [NSMutableArray array];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"headerList.plist" ofType:nil];
    NSDictionary *diaryList = [NSDictionary dictionaryWithContentsOfFile:path];


    NSArray *keyVal = diaryList.allKeys;
    NSArray *valueVal = diaryList.allValues;

    NSInteger keycount = keyVal.count;

    for (NSInteger i = 0; i< keycount ; i++) {

        DDSectionModel *sectionModel = [[DDSectionModel alloc] init];
        sectionModel.isExpanded = NO;
        sectionModel.sectionTitle = keyVal[i];

        NSMutableArray *cellArr = [NSMutableArray array];

        NSInteger valuCount = ((NSArray *)valueVal[i]).count;

        for (NSInteger j = 0; j< valuCount; j++) {

            DDCellModel *cellModel = [[DDCellModel alloc] init];
            cellModel.title = valueVal[i][j];
            [cellArr addObject:cellModel];

        }

        sectionModel.cellModels = cellArr;
        [dataArr addObject:sectionModel];

    }

     finished(dataArr);

}

3.接着我们自定义一下DDTableViewHeader

//设置view的 subviews
- (void)setupItems{

    //右上角箭头图片
    self.directionImageView.image = [UIImage imageNamed:@"brand_expand"];
    self.directionImageView.frame = CGRectMake(ScreenW - 30, (44-8)/2, 15, 8);
    [self.contentView addSubview:self.directionImageView];

    //btn覆盖header,相应点击
    UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, ScreenW, 44)];
    button.backgroundColor = [UIColor clearColor];

    [self.contentView addSubview:button];
    [button addTarget:self action:@selector(headerClick:) forControlEvents:UIControlEventTouchUpInside];
    self.contentView.backgroundColor = [UIColor defaultColor];
    self.contentView.layer.borderColor = [UIColor whiteColor].CGColor;
    self.contentView.layer.borderWidth = 0.5;

}
- (void)headerClick:(UIButton *)btn{

    self.sectionModel.isExpanded = !self.sectionModel.isExpanded;

    [UIView animateWithDuration:0.25 animations:^{

        if (!self.sectionModel.isExpanded) {

            self.directionImageView.transform = CGAffineTransformIdentity;

        }else{
            self.directionImageView.transform = CGAffineTransformMakeRotation(M_PI);
        }

    }];
    if (self.HeaderClickedBack) {
        self.HeaderClickedBack(self.sectionModel.isExpanded);
    }


}
- (void)setSectionModel:(DDSectionModel *)sectionModel{

    _sectionModel = sectionModel;

    self.textLabel.text = sectionModel.sectionTitle;

    if (!_sectionModel.isExpanded) {

        self.directionImageView.transform = CGAffineTransformIdentity;

    }else{

        self.directionImageView.transform = CGAffineTransformMakeRotation(M_PI);
    }

}

4.剩下就负责构建UITableView了

首先我们需要在ViewDidLoad中加载数据源,赋值给DataSoruce

 [DDSectionModel loadData:^(NSArray *models) {
 
        self.dataSource = models;
        
    }];

实现相应的#pragma mark - Table view data source代理方法

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return self.dataSource.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.dataSource[section].isExpanded ? (self.dataSource[section].cellModels.count) : 0;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MoreTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"myCellID"];

    if (!cell) {

        cell = [[MoreTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"myCellID"];
    }
    cell.cellModel = self.dataSource[indexPath.section].cellModels[indexPath.row];
    return cell;
}


- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{

    DDTableViewHeader *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"header"];

    if (!headerView) {
        headerView = [[DDTableViewHeader alloc] initWithReuseIdentifier:@"header"];
    }
    headerView.sectionModel = self.dataSource[section];
    headerView.HeaderClickedBack = ^(BOOL isExpand){

        [tableView reloadSections:[[NSIndexSet alloc] initWithIndex:section] withRowAnimation:UITableViewRowAnimationAutomatic];
    };

    return  headerView;
}

这样我们就能够优雅的实现了一个可点击展开与收回的UITableview,当然有人可能觉得,这样方式太依赖于模型,其实本文的耦合性已经很低了,Tableview列表的展示还需要依赖于数据源呢,只不过我们是构建了一个可维护的模型,可以随时扩展,当然大家有好的建议可以提出来,一起学习。
本文demo地址:https://github.com/markdashi/DDUITableview.git

搜索CocoaChina微信公众号:CocoaChina
微信扫一扫
订阅每日移动开发及APP推广热点资讯
公众号:
CocoaChina
我要投稿   收藏文章
上一篇:什么时候使用RunLoop
下一篇:老司机出品—疯狂造轮子之图片异步下载类
我来说两句
发表评论
您还没有登录!请登录注册
所有评论(0

综合评论

相关帖子

sina weixin mail 回到顶部