iOS实现三列表格点选(附Demo)

项目中常用到列表赛选,一般来说都是一列、两列的,这段时间我自己项目用到了三列,网上也没见到很好的Demo参考,无奈自己按着自己的想法写了一个,存粹提供一种方法供大家参考下。

这个Demo我仅仅写了一个三列的表格,没有做表头item的封装。至于一列、两列就更简单了,几乎毫无难度,大家自行撸过去即可。
先上效果图:

Untitled,,.gif

使用:我想足够简单了.......

- (void)viewDidLoad {
    [super viewDidLoad];

    self.dropView = [[YLDropDownTableView alloc] initWithFrame:CGRectMake(0, 40 + 64, self.view.frame.size.width, 350)];
    self.dropView.delegate = self;
    [self.view addSubview:self.dropView];
    //构造数据
    for (int i = 0; i < 6; i++) {
        //一维数组
        [self.dropView.firstData addObject:[NSString stringWithFormat:@"第一列 %d",i]];
        NSMutableArray *two0 = [NSMutableArray array];
        NSMutableArray *third0 = [NSMutableArray array];
        for (int j = 0; j < 7; j++) {
            [two0 addObject:[NSString stringWithFormat:@"第二列 %d-%d",i,j]];
            NSMutableArray *third1 = [NSMutableArray array];
            for (int k = 0; k < 15; k++) {
                [third1 addObject:[NSString stringWithFormat:@"第三列 %d-%d-%d",i,j,k]];
            }
            [third0 addObject:third1];
        }
        //二维数组
        [self.dropView.secondeData addObject:two0];
        //三维数组
        [self.dropView.thirdData addObject:third0];
    }
    [self.dropView reloadData];
}
//show
- (IBAction)showDropView:(id)sender {
    
    [self.dropView show];
    
}
#pragma mark -- YLDropDownTableViewDelegate
- (void)didSeleted_ylDropDownWithFirstStr:(NSString *)firstTitle andSecondTitle:(NSString *)secondTitle andThirdTitle:(NSString *)thirdTitle {
    NSLog(@"1 : %@  2 : %@  3 : %@", firstTitle, secondTitle, thirdTitle);
}
//点击下部蒙版
- (void)touchShadowView {
    NSLog(@"点击了蒙版");
}

代码不多,就是三列构造数据第三列需要三维数组,大家注意下就行了。下面简单说下核心代码的思路。

我认为这个只有一个难点,就是数据的记录,即上次点击后的如果改变这行的文字状态,甚至加上一个✅选择。

在数据记录上,我用了一个不高雅但是很方便的办法,用数组构造记录下标。

self.selectedArray = [NSMutableArray arrayWithArray:@[@"0", @"0",@"0"]];
self.IndexPathArray = [NSMutableArray arrayWithArray:@[@"0",@"0"]];

上面两行代码,如果我不解释你可能无比懵逼。第一个数组是我用来记录最终选择的下标值(也就是点击了第三列),一共三列三个元素。

第二个数组是我用来记录每次点选第一列和第二列时候的下标的,用于刷新第二列和第三列的数据。这个只有两个元素,仅仅记录第一列点击和第二列点击即可,因为点了第二列第三列会刷新,这时候没有点击第三列,self.selectedArray这个数组就不会被赋值,所以不需要三个元素。
当需要的第三个时候也就意味着点击了第三列做了最终选择,这时候直接对self.selectedArray赋值即可。如下:

#pragma mark - UITableViewDelegate,

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    if (tableView == self.leftTableView) {

        self.IndexPathArray[0] = [NSString stringWithFormat:@"%ld", indexPath.row];
        //很重要的一步,把第二列的记录初始化,避免此时第二列已经点击被记录其他值
        //如果这个值大于下一次刷新的第二列的数组个数,会发生数组越界的崩溃
        //点击第一列,相当于后面两列数据从新分配,所以这里修改为初始值
        self.IndexPathArray[1] = @"0";
        [self.midTableView reloadData];
        [self.rightTableView reloadData];
    }else if (tableView == self.midTableView) {
        self.IndexPathArray[1] = [NSString stringWithFormat:@"%ld", indexPath.row];
        [self.rightTableView reloadData];
    }else {
        NSInteger selected2 = [self.IndexPathArray[1] integerValue];
        UIImageView *imgV = [cell.contentView viewWithTag:101];
        if (selected2 == indexPath.row && [self.selectedArray[0] isEqual: self.IndexPathArray[0]] && [self.selectedArray[1] isEqual:self.IndexPathArray[1]]) {
            imgV.hidden = NO;
        }
        //进行赋值。记录最终所选项的对应index
        self.selectedArray[0] = self.IndexPathArray[0];
        self.selectedArray[1] = self.IndexPathArray[1];
        self.selectedArray[2] = [NSString stringWithFormat:@"%ld",indexPath.row];
        
        //刷新3列
        [self.leftTableView reloadData];
        [self.midTableView reloadData];
        [self.rightTableView reloadData];
        
        if (self.delegate && [self.delegate respondsToSelector:@selector(didSeleted_ylDropDownWithFirstStr:andSecondTitle:andThirdTitle:)]) {
            UILabel *label = [cell.contentView viewWithTag:100];
            [self.delegate didSeleted_ylDropDownWithFirstStr:self.firstData[[self.selectedArray[0] integerValue]] andSecondTitle:self.secondeData[[self.selectedArray[0] integerValue]][[self.selectedArray[1] integerValue]] andThirdTitle:label.text];
        }
        //延迟0.1为了等待UI刷新动画
        [self performSelector:@selector(dismiss) withObject:self afterDelay:0.1];
    }

}

上面是我对三个列表点击时做的不同的处理。
其中有一处尤为重要,我已经写了备注。就是在点击第一列的时候。
这行代码

        self.IndexPathArray[1] = @"0";

当点击第一列的时候就意味着第二、三列的数据肯定会刷新,这时候如果你已经做了第二列选择。例如你选择了第二列第三个元素,再去点击第一列,一旦这时候第一列只有两个数据,必然发生数组越界崩溃。为什么这样呢?看下面代码


#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == self.leftTableView) {
        return self.firstData.count ? self.firstData.count : 0;
    }else if (tableView == self.midTableView) {
        NSInteger index = [self.IndexPathArray[0] integerValue];
        NSArray *array = self.secondeData[index];
        return array.count ? array.count : 0;
    }else {
        NSInteger index = [self.IndexPathArray[0] integerValue];
        NSInteger index1 = [self.IndexPathArray[1] integerValue];
        NSArray *array = self.thirdData[index][index1];
        return array.count ? array.count : 0;
    }

我们看到。第三列的数据是根据这行代码

NSInteger index1 = [self.IndexPathArray[1] integerValue];

从这里拿到下标,在前面你点选了第二列。那这个被改成了3.这时候找数据一共只有两个,你去找第三个,就崩了。因此当点选第一个列表的时候,我们有必要把这个数据设为最初始的值也就是0;这样拉取第二列和第三列数据的时候才不会有问题。

下面cell创建我也贴出来吧,为了方便,我直接在数据源方法里创建并且设置了cell样式

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
        YLInsetLabel *titleLabel = [[YLInsetLabel alloc] initWithFrame:CGRectMake(0, 0, 100, 44)];
        //设置label的�内边距
        titleLabel.insets = UIEdgeInsetsMake(0, 20, 0, 0);
        titleLabel.tag = 100;
        titleLabel.textColor = [UIColor blackColor];
        titleLabel.font = [UIFont systemFontOfSize:13];
        [cell.contentView addSubview:titleLabel];
        
        if (tableView == self.rightTableView) {
            UIImageView *imgV = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"list_selected"]];
            imgV.frame = CGRectMake(10, (44-15) / 2, 15, 15);
            imgV.hidden = YES;
            imgV.tag = 101;
            [cell.contentView addSubview:imgV];
            titleLabel.frame = CGRectMake(20, 0, self.frame.size.width - 200 - 20 - 20, 44);
        }else {
            cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.frame];
            cell.selectedBackgroundView.backgroundColor = [UIColor groupTableViewBackgroundColor];
        }
    }
    UILabel *label = [cell.contentView viewWithTag:100];
    if (tableView == self.leftTableView) {
        cell.backgroundColor = [UIColor whiteColor];
        label.text = self.firstData[indexPath.row];
        //满足一个条件,即可认为是上次选择项
        if ([self.selectedArray[0] integerValue] == indexPath.row) {
            label.textColor = SelectedColor;
        }else {
            label.textColor = [UIColor blackColor];

        }
    }else if (tableView == self.midTableView) {
        cell.backgroundColor = [UIColor colorWithRed:250/255. green:250/255. blue:250/255. alpha:1];
        NSInteger selected = [self.IndexPathArray[0] integerValue];
        label.text = self.secondeData[selected][indexPath.row];
        //同时满足两个tiao'j.即认为是上次选择的cell
        if([self.selectedArray[0] isEqual:self.IndexPathArray[0]] && [self.selectedArray[1] integerValue] == indexPath.row) {
            label.textColor = SelectedColor;
        }else {
            label.textColor = [UIColor blackColor];
        }
    }else {
        
        cell.backgroundColor = [UIColor groupTableViewBackgroundColor];
        NSInteger selected1 = [self.IndexPathArray[0] integerValue];
        NSInteger selected2 = [self.IndexPathArray[1] integerValue];
        UIImageView *imgV = [cell.contentView viewWithTag:101];
        
        //同时满足三个条件,即认为是上次选择的cell
        if ([self.selectedArray[2] integerValue] == indexPath.row && [self.selectedArray[0] isEqual:self.IndexPathArray[0]] && [self.selectedArray[1] isEqual:self.IndexPathArray[1]]) {
            imgV.hidden = NO;
            label.textColor = SelectedColor;
        }else {
            imgV.hidden = YES;
            label.textColor = [UIColor blackColor];
        }
        
        label.text = self.thirdData[selected1][selected2][indexPath.row];
    }
    
    return cell;
    
}

一大堆,确实不利于观看,你们可以把这个单独写进cell类中,让代码清爽一些。

其他我就不啰嗦了,如果有帮助给个喜欢。

GitHub Demo 喜欢请star : 传送门
iOS技术交流群:511860085 欢迎加入!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容