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 条评论
登录 后参与评论

相关文章

来自专栏c#开发者

IOS5开发-控件位置适应屏幕旋转代码

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation  ...

34511
来自专栏DannyHoo的专栏

cell高度的缓存1——利用字典进行缓存

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

811
来自专栏iOS122-移动混合开发研究院

Colours–颜色库,包含100种预定义的颜色和方法

简介 Colours–颜色库,包含各种100种预定义的颜色和方法,可以简化颜色相关的开发工作. 最新示例: 点击下载 快速入门 安装 通过Cocoapods安装...

1998
来自专栏DannyHoo的专栏

xml解析代码

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

873
来自专栏陈满iOS

iOS·数组元素逆序方案

求解: strArr的反序数组strRevArr,即元素顺序分别为e,d,c,b,a。

744
来自专栏吾爱乐享

java之学习calendar类的概述和方法案例教程

984
来自专栏移动端开发

UICollectionView 很简单的写个瀑布流

你项目中要用到它吗? 可能会在你的项目中用到这玩意,最近也是要用就简单的写了一个 Demo。没多少代码,就不放Git了,下面会详细点的说说代码的,要还有什么问...

1937
来自专栏我杨某人的青春满是悔恨

教你写个多表视图

如图所示的多表视图是一个很常用的东西,之前我是用UIScrollView和UITableViewController做的。把当前的控制器作为一个父控制器,添加三...

793
来自专栏向治洪

ios仿斗鱼界面

前言 过去的2016年是一个直播年,各大平台都相继接入了直播频道,电商,社交…更是火了一批做视频的,譬如喵播,映客,都斗鱼等直播平台。全民直播,一下子掀起了直播...

2029
来自专栏编程之路

Swift纯代码 UICollectionView 分组显示、Cell圆角、选中变色

上一篇介绍了如何使用swift纯代码构建UIColletionView,本篇继续介绍如何对其分组、设置分组标题、cell 圆角、选中变色。 效果图如下:

851

扫码关注云+社区