2.13 选择器控件——UIPickerView

UIPickerView是一个简易的列表控件,用于提供有限个数的选项供用户选择,UIPickerView的UI设计十分漂亮,是iOS系统特有的UI模式。在实际应用中,UIPickerView的应用也十分广泛,如省市县选择列表、时间选择、日期选择等都可以通过UIPickerView设计。

2.13.1 创建一个UIPickerView控件

UIPickerView与之前章节中的UI控件有着很大不同,UIPickerView更加复杂一些,它是通过代理和数据源的方法对其进行设置和数据源填充的,这种控件的设计模式也是代理模式的应用之一。使用Xcode开发工具创建一个名为UIPickerViewTest的工程,在ViewController类的声明部分添加遵守相应的协议,这里需要遵守两个协议,分别是UIPickerViewDelegate和UIPickerViewDataSource。

Swift语言版本:

        class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate

Objective-C语言版本:

        @interface ViewController ()<UIPickerViewDataSource, UIPickerViewDelegate>
        @end

在viewDidLoad方法中添加如下代码。

Swift语言版本:

            override func viewDidLoad() {
                super.viewDidLoad()
                let picker = UIPickerView(frame: CGRect(x: 20, y: 100, width: 280, height: 150))
                picker.delegate = self
                picker.dataSource = self
                self.view.addSubview(picker)
            }

Objective-C语言版本:

        - (void)viewDidLoad {
            [super viewDidLoad];
            UIPickerView * picker = [[UIPickerView alloc]initWithFrame:CGRectMake(20, 100, 280, 150)];
            picker.delegate=self;
            picker.dataSource=self;
            [self.view addSubview:picker];
        }

上面的代码中除了对UIPickerView进行创建和初始化工作外,还设置了当前类对象为其数据源和代理。在ViewController类中实现如下代理方法。

Swift语言版本:

            func numberOfComponents(in pickerView: UIPickerView) -> Int {
                return 2
            }
            func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
                return 10
            }
            func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) ->String? {
                return "\(component)分区\(row)行数据"
            }
            func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
                return 44
            }
            func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
                return 144
            }

Objective-C语言版本:

        -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
            return 2;
        }
        -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
            return 10;
        }
        -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:
    (NSInteger)component{
            return [NSString stringWithFormat:@"%lu分区%lu数据", component, row];
        }
        -(CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
            return 44;
        }
        -(CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component{
            return 140;
        }

· numberOfComponentsInPickerView方法返回一个整型数据,用于设置UIPickerView视图的分区数,也可以理解为选择列表的列数。

· pickerView:numberOfRowsInComponent方法的返回值设置UIPickerView每个分区的行数,参数component用于判断具体的分区。

· titleForRow方法的返回值设置列表中每一行的数据,这个方法中的两个参数row和component分别用于区分行与列。

· rowHeightForComponent方法的返回值设置具体行的行高。

· widthForComponent方法的返回值设置分区的宽度,即列的宽度。

运行工程,效果如图2-39所示。

图2-39 UIPickerView控件

2.13.2 UIPickerView选中数据时的回调代理

UIPickerView总是会展现几列数据帮助用户进行快速选择,当用户上下滑动UIPickerView列表时,列表中的数据会进行上下滑动移动;当移动动作停止时,这时悬停在UIPickerView列表中间的数据就是用户选中的数据,并且此时系统会调用UIPickerView的如下代理方法通知开发者用户的选择。

Swift语言风格:

            func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
                print("\(component)分区\(row)行")
            }

Objective-C风格:

        -(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row
    inComponent:(NSInteger)component{
            NSLog(@"%lu, %lu", row, component);
        }

在调用didSelectRow方法时,row参数和component参数会将用户选择的行和分区的信息传递给开发者。