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类中,让代码清爽一些。

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏一“技”之长

iOS UITableView代理方法详解 原

在上一篇博客中,http://my.oschina.net/u/2340880/blog/404605,我将IOS中tableView(表视图)的一些常用方法总...

664
来自专栏Rindew的iOS技术分享

iOS中runtime的简单用法——动态绑定

1895
来自专栏Y大宽

RNA-seq数据分析工具详细介绍(从质量控制到可视化)

923
来自专栏菩提树下的杨过

Flash在线拍摄用户头象

很多网站在上传用户头象时,除了传统方式上传外,都支持在线摄像头拍照并做简单编辑,完成之后再将图象数据提交到服务端(比如ASP.Net),这几天正好需要这个功能,...

2788
来自专栏hotqin888的专栏

MeritMS+jQuery.Gantt价值管理系统增加项目进度展示

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

1101
来自专栏哈雷彗星撞地球

iOS 中获取某个视图的截图

最近在做SDK的截图,想触发类似系统的截屏功能,找了一圈,总结一下靠谱的几种方式。 我写了个UIView 的category,将这几种方式封装和简化了一下。

1113
来自专栏ShaoYL

Quartz2D知识点聚合案例

27310
来自专栏一“技”之长

iOS NSTimer 定时器用法总结 原

NSTimer在IOS开发中会经常用到,尤其是小型游戏,然而对于初学者时常会注意不到其中的内存释放问题,将其基本用法总结如下:

521
来自专栏菩提树下的杨过

java学习:Hibernate学习-用oracle sequence序列生成ID的配置示例

接上回继续,TMP_EMP中的ID是根据序列SQ_TMP_EMP来生成的,需要在TmpEmp.hbm.xml中设置:   <id name="id" type=...

1849
来自专栏谈补锅

ios网络编程学习

在网络编程中,从服务器获取的数据格式大致分为两种:JSON和XML。其中JSON作为一种轻量级的数据交换格式,正在逐步取代XML, 成为网络数据的通用格式。

1442

扫码关注云+社区