零基础iOS开发学习日记—控件篇—UIPickView

开头

UIPickView

实际用处

  • 通过设置输入控件的inputView,成为自定义键盘
  • 实现菜单选择,时间选择,国家地区选择等功能

基本用法

  • UIPickerView的使用有以下几个关注点
  1. 列数,每列的个数,通过UIPickerViewDataSource数据源方法设置
  2. 显示的是文字,还是图片,通过UIPickerViewDelegate代理方法设置
  3. 设置UIPickerView每一个元素的长度和宽度,通过UIPickerViewDelegate的代理方法
UIPickerView *pickerView = [UIPickerView new];
pickerView.frame = CGRectMake(0, 100, [UIScreen mainScreen].bounds.size.width, 300);
pickerView.dataSource = self;
pickerView.delegate = self;
pickerView.backgroundColor = [UIColor redColor];
[self.view addSubview:pickerView];
复制代码
  • 设置列数,和每列的个数。实际开发中,设置每列的个数中需要通过if语句进行列的判断,进行不同内容的显示,例如在地区的功能实现中,第一列为不同的省,而第二列要根据第一列的省显示不同的市
//显示两列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
    return 2;
}
//每列显示10行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
    return 10;
}
复制代码
  • 设置显示内容,显示文字或者图片,选一个函数实现即可
  • 我在使用过程中,发现返回图片的时候无论frame,设置为多少,还是显示UIPickerView中选项视图的大小
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
    return @"mzx";
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"dv_icon1"]];
    imageView.contentMode = UIViewContentModeScaleAspectFit;
    imageView.frame = CGRectMake(0, 0, 0, 1000);
    return imageView;
}
复制代码
  • 设置UIPickerView里面元素的大小,这里需要注意的一点如果设置为奇数列,比如三列,系统会保证中间一列为设置的大小,省下的空间分给左右两列
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
    return 100;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
    return 100;
}
复制代码

地区功能

  • 知道了基本的设置方法,功能的实现围绕着下面亮点
  1. 数据的设置
  2. 刷新的时机
  • 下面的整理略过plist文件的解析,这部分放到功能篇整理,下列的例子可以将self.provinces理解为一个存着省的数组,而这个数组中的每一个对象的citys中都存着这个省中的市数字
  • 第一列的长度是省的个数,第二列的的个数是市的个数,而且是根据第一列的行数,找到对应数组的省对象,再找到这个对象的城市个数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    //如果是第0组省,行数就是模型数组数量
    if(component == 0)
    {
        return self.provinces.count;
    }
    //如果是第1组市,
    else
    {
        //获取显示的是哪个省
        //获取第0组选中的行号
        NSInteger selProIdx = [pickerView selectedRowInComponent:0];
        //从集合中获取数据
        SSProvince *selPro = self.provinces[selProIdx];
        //将返回的省保存
        self.selProvince = selPro;
        //根据省的城市数据去确定城市的行数
        return self.selProvince.cities.count;
    }
}
复制代码
  • 第一列返回的是,这个对象的省名,第二列返回的是,这个对象中的城市数组

这里会出现一个bug,如果第一列在滚动的时候滚动第二轮,会导致崩溃,崩溃原因是,并不是每一列的个数都是一样的,如果第一列滚到了较少的市的省,那么第二列继续滚就会导致数组越界或者系统不知道第二列的个数,所以要在选中的地方将选中省保存,让返回文字的代理方法,成一个静态的数据设置,让第二列滚动的数据始终是来自上一次省确定的,保证第二次滚的范围确定。

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    //第0组 省 返回省模型名称
    if (component == 0) {
        SSProvince *pro = self.provinces[row];
        return pro.name;
    }
    //第1组 市 根据第0组显示的省,把省里面的市返回
    else
    {
        //导致崩溃
        //NSInteger selProIdx = [pickerView selectedRowInComponent:0];
        //SSProvince *selPro = self.provinces[selProIdx];
        //return selPro.cities[row];
        return self.selProvince.cities[row];
    }
}
复制代码
  • 数据刷新,利用代理方法中的didSelectRow,监听选中状态,已更新数据。如果选中第一列,那么要更新第二列的数据;如果选中第二列,则导出两个数据。
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    //如果选中的是第0组 省,需要刷新城市
    if(component == 0)
    {
        [pickerView reloadComponent:1];
        //选中第一组第0行
        [pickerView selectRow:0 inComponent:1 animated:YES];
        
    }
    //获取省市的索引
    NSInteger selProIdx = [pickerView selectedRowInComponent:0];
    NSInteger selCityIdx = [pickerView selectedRowInComponent:1];
    //从集合中取数据
    SSProvince *selPro = self.provinces[selProIdx];
    NSString *selCity = self.selProvince.cities[selCityIdx];
    //赋值
    self.proLbl.text = selPro.name;
    self.cityLbl.text = selCity;
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享