美文网首页
iOS - 二级连动(tableview包含 collectio

iOS - 二级连动(tableview包含 collectio

作者: CDLOG | 来源:发表于2018-09-03 23:44 被阅读216次

    基本结构

    1,一级分类结构
    一个 tableview列表
    2,二级分类结构
    一个 tableview 的每个 cell 都是一个 collectionview
    根据一级分类选择的cell刷新二级分类 tableview
    3,二级分类带索引
    引用三方iOS列表的索引功能

    模型结构

    1,一级分类模型fModels
    核心属性(一级分类包含二级分类的所有信息)

    //记录一级分类是否选中,避免 cell 复用的 UI错误
    @property (assign,nonatomic) BOOL select;
    //带索引的二级品类信息
    @property (nonatomic,strong) NSDictionary <NSString *,NSArray *>*sModelDicts;
    //二级分类有序的索引数组,用于有序的加载二级分类 cell
    @property (strong,nonatomic) NSArray * secondIndexKeyArr;
    //二级分类序号对应的cell的高度,根据索引数组保存索引的高度信息 key:height
    @property (strong,nonatomic) NSMutableDictionary* secondHeightDicts;
    

    基本属性

    @property (nonatomic,assign) NSInteger fID;
    @property (nonatomic,strong) NSString * fName;
    

    2,二级分类模型sModel
    基本属性

    @property (nonatomic,assign) NSInteger sID;
    @property (nonatomic,strong) NSString * sName;
    @property (assign,nonatomic) BOOL select;
    

    加载一级分类和二级分类数据

    通过网络加载数据,数据格式为

    {
       Fmodel1的数据
      FModel1.SModel = {
                                    "索引1" :[ 该索引下的全部二级分类 ]
                                    "索引2" :[ 该索引下的全部二级分类 ]
                                }
     Fmodel2的数据
      FModel2.SModel = {
                                    "索引1" :[ 该索引下的全部二级分类 ]
                                    "索引2" :[ 该索引下的全部二级分类 ]
                                }
    }
    

    数据加载原理
    1,一级分类数据
    直接根据字典的方式加载
    2,二级分类数据
    ·首先将二级分类索引排序,保存到secondIndexKeyArr 数组
    ·遍历每个索引下的二级分类对象数组保存到sModelDicts字典
    ·将该字典保存到一级分类对象属性sModelDicts
    ·将一级分类对象属性添加到一级分类数组
    核心代码

    //成功获取网络数据
    if(success)
            {
    //            保存一级分类对象的数组
                NSMutableArray * fModels = [NSMutableArray array];
    //            遍历一级分类
                NSArray * cateArr = response[@"resultMap"][@"rows"];
                [cateArr enumerateObjectsUsingBlock:^(NSDictionary * obj, NSUInteger idx, BOOL * _Nonnull stop) {
    //               一个一级分类对象
                    FModel * model  = [[FModel alloc] init];
                    model.fID       = [obj[@"firstProductCategoryCodeId"] integerValue];
                    model.fName     = obj[@"firstProductCategoryName"];
    //                获取一级分类下的全部索引和对应的二级分类
                    NSDictionary * sDicts = obj[@"dataListCfs"];
                    // 将索引排序
                    NSArray *keys = sDicts.allKeys;
                    keys = [keys sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
                        NSComparisonResult result = [obj1 compare:obj2];
                        return result == NSOrderedDescending;
                    }];
    //                保存有序的二级分类索引
                    model.secondIndexKeyArr = [NSArray arrayWithArray:keys];
    //                创建二级分类字典
                    NSMutableDictionary * sModels = [NSMutableDictionary dictionary];
                
    //                遍历索引取得每个索引下的二级品类数组 每个索引对应该索引下的二级分类数组对象
                    [sDicts enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSArray* obj, BOOL * _Nonnull stop) {
    //                 遍历将每个二级品类数组下的数组转二级品类对象数组
                        NSMutableArray *sobjArr = [NSMutableArray array];
                        [obj enumerateObjectsUsingBlock:^(NSDictionary* sobj, NSUInteger idx, BOOL * _Nonnull stop) {
                            sModel * models = [[sModel alloc] init];
                            models.sID      = [sobj[@"secondProductCategoryCodeIds"] integerValue];
                            models.sName    = sobj[@"secondProductCategoryName"];
                            [sobjArr addObject:models];
                        }];
                        
                        [sModels setObject:sobjArr forKey:key];
                    }];
    //                将二级分类字典保存到一级分类
                    model.sModelDicts = [NSDictionary dictionaryWithDictionary:sModels];
                    [fModels addObject:model];
                    
                }];
                
            }
    

    控制器

    1,一级分类选中的复用问题
    第一个 cell 默认选中
    当点击 cell时,先将前一个 cell选中标志清除,再将当前 cell 选中,最后将当前 cell 赋值给选中cell属性
    2,选中时刷新二级分类列表

    //记录选中的一级分类,避免 cell 复用引起的 UI 问题
    @property (strong,nonatomic) FirstCategoryCell * FirstCell;
    //使用
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (tableView == self.FirstCategoryTable) {
            FirstCategoryCell *cell = [self.FirstCategoryTable cellForRowAtIndexPath:indexPath];
            self.FirstCell.leftLine.hidden = YES;
            cell.leftLine.hidden = NO;
            self.selectCellRow = indexPath.row;
            self.FirstCell = cell;
            self.selectIndex = indexPath.row;
            [self reloadIndex];
        }else{
            
        }
    }
    

    下面代码的主要功能
    1,根据选中的一级分类刷新二级分类
    2,切换一级分类时索引重新回到最上方
    3,相关的 tableView代理方法

    //选中的二级分类序号
    @property (assign,nonatomic) NSInteger  selectSection;
    //选择一级分类的索引
    @property (assign,nonatomic) NSInteger selectIndex;
    @property (assign,nonatomic) NSInteger selectCellRow;
    //选择的二级分类字典
    @property (strong,nonatomic) NSDictionary * sModelDicts;
    
    
    //根据选中的一级品类刷新二级品类
    -(void)reloadIndex{
    
        //        根据key来存储每个cell的高度
        self.fModels[self.selectIndex].secondHeightDicts = [NSMutableDictionary dictionary];
        [self.fModels[self.selectIndex].secondIndexKeyArr enumerateObjectsUsingBlock:^(NSString * obj, NSUInteger idx, BOOL * _Nonnull stop) {
            
            NSInteger count =  self.fModels[self.selectIndex].sModelDicts[obj].count;
            CGFloat height;
            if (count%self.rowItems>0) {
                height = (count/self.rowItems+1)*(self.itemHeight);
            }else{
                height = (count/self.rowItems)*(self.itemHeight);
            }
            [self.fModels[self.selectIndex].secondHeightDicts setObject:@(height) forKey:obj];
            
        }];
        //    刷新到顶部和序号刷新
        [self.SecondCategoryTable reloadData];
    //
        [self.SecondCategoryTable scrollToRow:0 inSection:0 atScrollPosition:UITableViewScrollPositionTop animated:YES];
        self.selectSection = 0;
        //    索引列表
        self.sModelDicts = [NSDictionary dictionaryWithDictionary:self.fModels[self.selectIndex].sModelDicts];
        SCIndexViewConfiguration *indexViewConfiguration = [SCIndexViewConfiguration configuration];
        self.SecondCategoryTable.sc_indexViewDelegate = self;
        self.SecondCategoryTable.sc_indexViewConfiguration = indexViewConfiguration;
        self.SecondCategoryTable.sc_translucentForTableViewInNavigationBar = YES;
        self.SecondCategoryTable.sc_indexViewDataSource = self.fModels[self.selectIndex].secondIndexKeyArr;
    }
    #pragma mark 索引刷新
    
    
    //每次重新选择一级品类刷新序号到顶部
    - (NSUInteger)sectionOfTableViewDidScroll:(UITableView *)tableView{
        if (tableView == self.SecondCategoryTable) {
            return self.selectSection;
        }
        return 0;
    }
    
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
        
        if ([scrollView isEqual: self.SecondCategoryTable]) {
            
            if (self.SecondCategoryTable.contentOffset.y > _oldY) {
                // 上滑
                _isUpScroll = YES;
            }
            else{
                // 下滑
                _isUpScroll = NO;
            }
            _isFirstLoad = NO;
        }
    }
    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
        
        // 获取开始拖拽时tableview偏移量
        
        _oldY = self.SecondCategoryTable.contentOffset.y;
        
    }
    
    - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section{
        
        if (tableView == self.SecondCategoryTable) {
            
            
            UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
            
            header.textLabel.textColor = color_custom(@"333333");
            
            header.contentView.backgroundColor = color_custom(@"FFFFFF");
            
            if(!_isUpScroll && (self.selectSection - section) == 1){
                
                //最上面组头(不一定是第一个组头,指最近刚被顶出去的组头)又被拉回来
                self.selectSection = section;
    
                
            }
        }
        
    }
    
    
    - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section{
        
        if(!_isFirstLoad && _isUpScroll){
            
            self.selectSection = section + 1;
            
            //最上面的组头被顶出去
            
        }
        
    }
    #pragma mark --tableViewDelegate
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        if (tableView == self.FirstCategoryTable) {
            return 1;
        }else{
            return self.fModels[self.selectIndex].sModelDicts.allKeys.count;
        }
    }
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        if (tableView == self.FirstCategoryTable) {
            return self.fModels.count;
        }else{
    //每个section都只有一个cell,里面是collection
            return  1;
        }
    }
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (tableView == self.FirstCategoryTable) {
            return 49;
        }else{
    //        根据索引取出每个key对应的高度
            NSString *key = self.fModels[self.selectIndex].secondIndexKeyArr[indexPath.section];
            CGFloat height = [self.fModels[self.selectIndex].secondHeightDicts[key] doubleValue];
            return height;
            
        }
    }
    
    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
    {
        if (tableView == self.SecondCategoryTable) {
            return self.fModels[self.selectIndex].secondIndexKeyArr[section];
        }
        return nil;
    }
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (tableView == self.FirstCategoryTable) {
            
            
            FirstCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:FirstCategoryCellID];
            cell.leftLine.hidden = YES;
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            if (indexPath.row == self.selectCellRow) {
                cell.leftLine.hidden = NO;
            }
            [cell setUpModel:self.fModels[indexPath.row]];
            return cell;
        }else{
            SecondCategoryCell *cell = [tableView dequeueReusableCellWithIdentifier:SecondCategoryCellID];
            NSString *key =  self.fModels[self.selectIndex].secondIndexKeyArr[indexPath.section];
            [cell setupArrModel:self.fModels[self.selectIndex].sModelDicts[key]];
            return cell;
        }
        
    }
    -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        if (tableView == self.FirstCategoryTable) {
            FirstCategoryCell *cell = [self.FirstCategoryTable cellForRowAtIndexPath:indexPath];
            self.FirstCell.leftLine.hidden = YES;
            cell.leftLine.hidden = NO;
            self.selectCellRow = indexPath.row;
            self.FirstCell = cell;
            self.selectIndex = indexPath.row;
            [self reloadIndex];
        }else{
            
        }
    }
    
    
    

    二级分类的 Cell 包含collection相关方法

    //加载数据。 注意要刷新 collectionview
    -(void)setupArrModel:(NSArray <sModel *>*)model{
        self.smodelArr = model;
        [self.SecondCollectionView reloadData];
    }
    
    #pragma mark - collection delegate
    
    -(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
    {
        return 1;
    }
    
    -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
    {
        NSLog(@"self.smodelArr.count = %ld",self.smodelArr.count);
        return self.smodelArr.count;
    }
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        NSTCollectionCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
        
        sModel * smodel = [self.smodelArr objectAtIndex:indexPath.row];
    //    sModel * smodel = [self.smodelArr ]
        [cell setUPsModel:smodel];
        [self.cellSet addObject:cell];
        if([self.delegate respondsToSelector:@selector(selectSModel)])
        {
            sModel * model = [self.delegate selectSModel];
            if([smodel isEqual:model])
            {
                SFModel * model = [[SFModel alloc] init];
                model.s_fModel = self.myModel;
                model.s_sModel = smodel;
                
                if([self.delegate respondsToSelector:@selector(cellDefaultModel:inCell:)])
                {
                    [self.delegate cellDefaultModel:model inCell:cell];
                }
            }
            else
                [cell setToNormalAnimation:NO];
        }
        
        return cell;
    }
    
    -(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
    {
        NSTCollectionCell * cell = (NSTCollectionCell *)[collectionView cellForItemAtIndexPath:indexPath];
        
        if([self.delegate respondsToSelector:@selector(canSelectModel:)])
        {
            if(self.single)
            {
                [self.cellSet enumerateObjectsUsingBlock:^(NSTCollectionCell * obj, BOOL * _Nonnull stop) {
                    
                    [obj setToNormalAnimation:YES];
                    
                }];
            }
            SFModel * model = [[SFModel alloc] init];
            model.s_fModel = self.myModel;
            model.s_sModel = cell.mySModel;
            BOOL can = [self.delegate canSelectModel:model];
            if(can)
            {
                if([self.delegate respondsToSelector:@selector(selectModel:inCell:)])
                {
                    [self.delegate selectModel:model inCell:cell];
                }
                else
                    [cell selectModel];
            }
        }
        else
            [cell selectModel];
    }
    
    #pragma mark - UICollectionViewDelegateFlowLayout
    
    -(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        return CGSizeMake(self.frame.size.width/3 - 8, 60);
    }
    
    

    因为是在开发中写的代码,就不上 demo 了,需要的可以参考一下。

    相关文章

      网友评论

          本文标题:iOS - 二级连动(tableview包含 collectio

          本文链接:https://www.haomeiwen.com/subject/lckwwftx.html