UITableview 優雅的展開與收回

最近為項目的功能需求準備著,有一個很簡單點擊展開與收縮的功能需求,以前Swift中寫過一個類似的功能,但是個人覺得不是特別好,當時就因為cell的復用導致了bug,并且這個需求是一直OC維護的項目,所以還是打算重寫一個,現將項目中這個功能模塊抽出來,與有相關需求的朋友分享一下。
首先上一下效果圖:

效果圖

1.首先說一下這個效果的思路:主要是通過維護一個模型來構建通過UITableviewCell 的列表

可維護的模型

本文主要的模型如上,并且這個模型可擴展性非常強,舉個簡單的例子的,DDSectionModel這個模型維護的是UITableViewHeaderFooterView,你可以將HeaderFooterView自定義為任何符合你需求的view;當然DDCellModel這個模型維護的是來維護cell,你可以定義cell來滿足你的需求.

DDSectionModel這個模型中有一個加載數據源的方法,當然你可以將此方法單獨定一個類或者定義一個協議去加載數據來降低耦合度,本文采用構建plist來當做數據源:

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

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容