基于省市区展示的tableView多层展开和折叠

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">话不多说,先上图:</span>


1.下面我首先说一下实现这个功能的基本思路:

tableView 展示省市的功能,我相信大家都会,将省名作为表头,将市名作为每个cell;对于展开和折叠省份操作,其基本原理就是对于每个section数据源,设一个标识符,记录它的状态是展开还是折叠,然后对于折叠状态就是将-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section方法返回0,展开时设为正常的cell数量.但是对于每个cell上显示的市,怎么点击展开和关闭呢,因为tableVIew的协议方法没有类似返回cell下视图数量的方法,只能在点击cell的方法里自己设计了,这里我采用的是添加和删除cell的操作,来达到展开和折叠每个cell,也就是每个市.

2.接下来我以我这个demo来解释下具体的实现步骤:

首先展示下plist文件内容,也就是省市区的结构


下面我们正式开始:

#define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT [UIScreen mainScreen].bounds.size.height

//MUSer返回16进制的颜色
#define BACKGROUND_WHITE_COLOR_CODE [MUser hexStringToColor:@"#12d2a1"]

@interface ViewController ()<UITableViewDataSource,UITableViewDelegate>

@property(nonatomic,strong)UITableView *myTableView;
@property(nonatomic,strong)NSMutableArray *dataSource;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.dataSource =[NSMutableArray array];
    [self setNav];
    [self createUI];
    [self loadData];
}

-(void)setNav
{
    self.title =@"省市区列表";
}


-(void)createUI
{
    UITableView *mytableView =[[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT) style:UITableViewStylePlain];
    //无分割线
    mytableView.separatorStyle =UITableViewCellSeparatorStyleNone;
    mytableView.showsHorizontalScrollIndicator =NO;
    mytableView.delegate =self;
    mytableView.dataSource =self;
    [self.view addSubview:mytableView];
    self.myTableView =mytableView;
    
}

//加载本地plist文件  需要说明一下就是获取本地文件的方法和字典数组转模型数组的方法,为了省事,我采用了MJExtension,因为这不是重点,故不多做介绍了
-(void)loadData
{
    NSMutableArray *dataArr =[NSMutableArray array];
    //MJ获取本地文件的方法
    dataArr =[NSMutableArray objectArrayWithFilename:@"longAddress.plist"];
    //字典数组 -> 模型数组  用模型调用 返回数组
    self.dataSource =[itemModel objectArrayWithKeyValuesArray:dataArr];

}


下面是tableVIew的协议方法

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return _dataSource.count;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    itemModel *model =self.dataSource[section];
    
    //核心设计方法,就是把要关闭的组row的数量设置为0 model的isClose属性在点击省份时修改
    if(model.isClose)
    {
        return 0;
    }
    //非关闭组的数量设置正常
    return [model.regions count];
    
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *string =@"string";
    UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:string];
    //设置cell没有选中效果
    cell.selectionStyle =UITableViewCellSelectionStyleNone;
    if(cell == nil)
    {
        cell =[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:string];
    }
    
    //判断regions数组里面对应的位置上是否是CtiyModel 因为区县的信息是以CityModel 加入到数据源中相应的位置
    if([[self.dataSource[indexPath.section] regions][indexPath.row] isKindOfClass:[CityModel class]])
    {
        //获取区县模型
        CityModel *model =[self.dataSource[indexPath.section] regions][indexPath.row];
        cell.textLabel.text =[NSString stringWithFormat:@"     %@", model.cityLocationName];

    }else
    {
        cell.textLabel.text =[[self.dataSource[indexPath.section] regions][indexPath.row] provienceName];
    }
    
    return cell;
}

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 44;
}

//设计cell的头部视图
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    UIView *view =[[UIView alloc]init];
    view.tag =section;
    view.userInteractionEnabled =YES;
    UITapGestureRecognizer *tap =[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapView:)];
    [view addGestureRecognizer:tap];
    view.backgroundColor =BACKGROUND_WHITE_COLOR_CODE;
    UILabel *label =[[UILabel alloc]initWithFrame:CGRectMake(20, 0, 80, 44)];
    
    //tableView header 显示身份名称
    label.text =[_dataSource[section] provienceName];
    label.textAlignment =NSTextAlignmentLeft;
    [view addSubview:label];

    return view;
}

//省份点击事件
-(void)tapView:(UITapGestureRecognizer *)tap
{
    NSInteger index =tap.view.tag;
    NSIndexSet *set =[NSIndexSet indexSetWithIndex:index];
    itemModel *item =self.dataSource[index];
    NSLog(@"点击了%@",item.provienceName);
    
    //修改section的关闭和打开
    item.isClose = !item.isClose;
    
    //刷新section的方法
    [self.myTableView reloadSections:set withRowAnimation:UITableViewRowAnimationFade];
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //判断点击的cell 对应的数据是否是city
    if([[self.dataSource[indexPath.section] regions][indexPath.row] isKindOfClass:[CityModel class]])
    {
        CityModel *model =[self.dataSource[indexPath.section] regions][indexPath.row];
        NSLog(@"点击了%@",model.cityLocationName);
        return;
    }

    
    //如果不是city的情况下
    NSArray *cityArr =[[self.dataSource[indexPath.section] regions][indexPath.row] city];
    RegionsModel *model =[self.dataSource[indexPath.section] regions][indexPath.row];
    NSMutableArray *pathArr =[NSMutableArray array];
    
    //判断cell是否打开
    if(model.isOpen)
    {
        NSLog(@"关闭%@组",model.provienceName);
        for(int i =0;i<cityArr.count;i++)
        {
            //获取添加的每个indexPath
            NSIndexPath *path =[NSIndexPath indexPathForRow:indexPath.row+i+1 inSection:indexPath.section];
            [pathArr addObject:path];
            //将要删除的cell上的数据从数据源中移除
            [[self.dataSource[indexPath.section] regions] removeObjectAtIndex:indexPath.row+1];
            model.isOpen =NO;
        }
        [tableView beginUpdates];
        
        //删除IndexPaths 数组
        [tableView deleteRowsAtIndexPaths:pathArr withRowAnimation:UITableViewRowAnimationBottom];
        [tableView endUpdates];
    }
    else
    {
         NSLog(@"打开%@组",model.provienceName);
        for(int i =0;i<cityArr.count;i++)
        {
            //获取添加的每个indexPath
            NSIndexPath *path =[NSIndexPath indexPathForRow:indexPath.row+i+1 inSection:indexPath.section];
            [pathArr addObject:path];
            //将要添加的cell上的数据加到数据源中
            [[self.dataSource[indexPath.section] regions] insertObject:cityArr[i] atIndex:indexPath.row+1+i];
            model.isOpen =YES;
        }
        [tableView beginUpdates];
         //增加IndexPaths 数组
        [tableView insertRowsAtIndexPaths:pathArr withRowAnimation:UITableViewRowAnimationBottom];
        [tableView endUpdates];
    }
}

以上部分就是核心代码部分,为了方便大家查看,我把其他的模型demo也附上,省市区,各建立了一个模型,一共三个模型.需要说明的时,模型的构建我也利用到了MJExtension,感兴趣的同学可以自行研究下.

首先是省模型,大家可以参照plist文件,

#import <Foundation/Foundation.h>


@interface itemModel : NSObject

@property(nonatomic,copy)NSString *provicenCode; //城市编码
@property(nonatomic,copy)NSString *provienceName; //城市名称
@property(nonatomic,assign)BOOL isClose; //记录section的状态
@property(nonatomic,strong)NSMutableArray *regions; //城市数组
@end

#import "itemModel.h"
#import "RegionsModel.h"
#import "MJExtension.h"

@implementation itemModel

+(NSDictionary *)objectClassInArray
{
    return @{@"regions":[RegionsModel class]};

}


@end

下面是市模型,同样可以参考plist文件截图:

#import <Foundation/Foundation.h>
#import "CityModel.h"

@interface RegionsModel : NSObject

@property(nonatomic,copy)NSString *provicenCode; //城市编码
@property(nonatomic,copy)NSString *provienceName; //城市名称

@property(nonatomic,assign)BOOL isOpen; //记录section的状态
@property(nonatomic,assign)BOOL isCity; //判断cell是否是city

@property(nonatomic,strong)NSArray *city; //城市数组

@property(nonatomic,strong)CityModel *cityModel; //添加的city模型


@end

#import "RegionsModel.h"
#import "MJExtension.h"
#import "CityModel.h"

@implementation RegionsModel

+(NSDictionary *)objectClassInArray
{
    return @{@"city":[CityModel class]};
}

@end


最后是区县模型

#import <Foundation/Foundation.h>

@interface CityModel : NSObject

@property(nonatomic,copy)NSString *cityLocationName; //区县名称
@property(nonatomic,copy)NSString *cityLocationCode; //区县编码

@end

#import "CityModel.h"

@implementation CityModel

@end

至此,功能和代码全部奉上,希望对大家有所帮助,如果区县下面还有乡镇的话,按照这种方式同样可以实现.




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值