1. 程式人生 > >基於省市區展示的tableView多層展開和摺疊

基於省市區展示的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 
[email protected]
"省市區列表"; } -(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 [email protected]"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

至此,功能和程式碼全部奉上,希望對大家有所幫助,如果區縣下面還有鄉鎮的話,按照這種方式同樣可以實現.