开头
- 这是分篇章,整篇请看零基础iOS开发学习日记
UIPickView
实际用处
- 通过设置输入控件的
inputView
,成为自定义键盘 - 实现菜单选择,时间选择,国家地区选择等功能
基本用法
UIPickerView
的使用有以下几个关注点
- 列数,每列的个数,通过
UIPickerViewDataSource
数据源方法设置 - 显示的是文字,还是图片,通过
UIPickerViewDelegate
代理方法设置 - 设置
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;
}
复制代码
地区功能
- 知道了基本的设置方法,功能的实现围绕着下面亮点
- 数据的设置
- 刷新的时机
- 下面的整理略过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