前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS实现三列表格点选(附Demo)

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

作者头像
Raindew
发布2018-06-14 14:34:02
8280
发布2018-06-14 14:34:02
举报
项目中常用到列表赛选,一般来说都是一列、两列的,这段时间我自己项目用到了三列,网上也没见到很好的Demo参考,无奈自己按着自己的想法写了一个,存粹提供一种方法供大家参考下。

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

Untitled,,.gif

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

代码语言:javascript
复制
- (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(@"点击了蒙版");
}

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

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

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

代码语言:javascript
复制
self.selectedArray = [NSMutableArray arrayWithArray:@[@"0", @"0",@"0"]];
self.IndexPathArray = [NSMutableArray arrayWithArray:@[@"0",@"0"]];

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

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

代码语言:javascript
复制
#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];
    }

}

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

代码语言:javascript
复制
        self.IndexPathArray[1] = @"0";

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

代码语言:javascript
复制
#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;
    }

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

代码语言:javascript
复制
NSInteger index1 = [self.IndexPathArray[1] integerValue];

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

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

代码语言:javascript
复制
- (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类中,让代码清爽一些。

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.03.15 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 项目中常用到列表赛选,一般来说都是一列、两列的,这段时间我自己项目用到了三列,网上也没见到很好的Demo参考,无奈自己按着自己的想法写了一个,存粹提供一种方法供大家参考下。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档