UIPickerView直接继承了UIView,没有继承UIControl,因此,它不能像UIControl那样绑定事件处理方法,UIPickerView的事件处理由其委托对象完成。
UIPickerView控件常用的属性和方法如下。
Ø numberOfComponents:获取UIPickerView指定列中包含的列表项的数量。该属性是一个只读属性。
Ø showsSelectionIndicator:该属性控制是否显示UIPickerView中的选中标记(以高亮背景作为选中标记)。
Ø - numberOfRowsInComponent::获取UIPickerView包含的列数量。
Ø - rowSizeForComponent::获取UIPickerView包含的指定列中列表项的大小。该方法返回一个CGSize对象。
Ø - selectRow:inComponent:animated::该方法设置选中该UIPickerView中指定列的特定列表项。最后一个参数控制是否使用动画。
Ø - selectedRowInComponent::该方法返回该UIPickerView指定列中被选中的列表项。
Ø - viewForRow:forComponent::该方法返回该UIPickerView指定列的列表项所使用的UIView控件。
UIDatePicker控件只是负责该控件的通用行为,而该控件包含多少列,各列包含多少个列表项则由UIPickerViewDataSource对象负责。开发者必须为UIPickerView设置
UIPickerViewDataSource对象,并实现如下两个方法。
Ø - numberOfComponentsInPickerView::该UIPickerView将通过该方法来判断应该包含多少列。
Ø - pickerView:numberOfRowsInComponent::该UIPickerView将通过该方法判断指定列应该包含多少个列表项。
如果程序需要控制UIPickerView中各列的宽度,以及各列中列表项的大小和外观,或程序需要为UIPickerView的选中事件提供响应,都需要为UIPickerView设置UIPickerViewDelegate委托对象,并根据需要实现该委托对象中的如下方法。
Ø - pickerView:rowHeightForComponent::该方法返回的CGFloat值将作为该UIPickerView控件中指定列中列表项的高度。
Ø - pickerView:widthForComponent::该方法返回的CGFloat值将作为该UIPickerView控件中指定列的宽度。
Ø - pickerView:titleForRow:forComponent::该方法返回的NSString值将作为该UIPickerView控件中指定列的列表项的文本标题。
Ø - pickerView:viewForRow:forComponent:reusingView::该方法返回的UIView控件将直接作为该UIPickerView控件中指定列的指定列表项。
Ø - pickerView:didSelectRow:inComponent::当用户单击选中该UIPickerView控件的指定列的指定列表项时将会激发该方法。
Interface Builder只支持为UIPickerView设置一个属性——Shows Selection Indicator,该属性用于控制是否显示UIPickerView中的选中标记(以高亮背景作为选中标记)。
下面通过程序来介绍 UIPickerView 的功能和用法。
单列选择器
对于单列选择器,只要控制 UIPickerView 的 dataSource 对象的 numberOfComponentsInPickerView: 方法返回 1 即可。
下面创建一个单列选择器,首先创建一个 Single View Application ,使用 Interface Builder 打开应用的界面设计文件,并将一个 UIPickerView 拖入界面设计文件中,为在程序中访问该控件,需要将该控件绑定到 picker IBOutlet 属性。
接下来开始修改控制器类,本例打算使用控制器类作为 UIPickerView 的 dataSource 和 delegate ,因此,程序需要让控制器类实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议。
修改控制器类的实现代码,主要就是实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议中的必要方法,其代码如下。
#import "ViewController.h"
@interface ViewController ()<UIPickerViewDataSource,UIPickerViewDelegate>
@property (weak, nonatomic) IBOutlet UIPickerView *pickView;
@property (nonatomic, strong) NSArray *ary;
@property (nonatomic, strong) NSArray *songAry;
@end
@implementation ViewController
/// 懒加载
- (NSArray *)ary {
if (!_ary) {
self.ary = [NSArray arrayWithObjects:@"汪峰",@"小黄人",@"张学友",@"凤凰传奇",@"筷子兄弟",nil];
}
return _ary;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pickView.dataSource = self;
self.pickView.delegate = self;
}
#pragma mark---- UIPickerViewDataSource,
/// 返回的列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
/// 每列返回的个数---列表数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return self.ary.count;
}
#pragma mark---- UIPickerViewDelegate
/// 指定列和列表项的标题文本
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return _ary[row];
}
/// 选中列表中得选项触发
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
UIAlertView *laert = [[UIAlertView alloc] initWithTitle:@"提示" message: [NSString stringWithFormat:@"选中的歌手的%@",_ary[row],] delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[laert show];
}
/// 返回指定列的宽度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 90;
}
@end
上面的程序首先初始化了一个 NSArray ,接下来的关键就是实现了 4 个用粗体字表示的方法,其中有两个方法来自 UIPickerViewDataSource 协议,分别用于控制该 UIPickerView 控件包含多少列、各列包含多少个列表项;另两个方法则来自 UIPickerViewDelegate ,最后一个粗体字方法负责为 UIPickerView 控件的选中事件提供响应——当用户选中该 UIPickerView 的某个列表项时,系统将会自动激发该方法,该方法的实现逻辑就是使用 UIAlertView 显示用户选择的对象。
多列选择器
对单列选择器而言,只要控制 UIPickerView 的 dataSource 对象的 numberOfComponentsInPickerView: 方法返回大于 1 的整数即可。
本节创建一个多列选择器,首先创建一个 Single View Application ,使用 Interface Builder 打开应用的界面设计文件,并将一个 UIPickerView 拖入界面设计文件中,为在程序中访问该控件,需要将该控件绑定到 picker IBOutlet 属性。
接下来修改控制器类,本例打算使用控制器类作为 UIPickerView 的 dataSource 和 delegate ,因此程序需要让控制器类实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议。
修改控制器类的实现代码,主要就是实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议中的必要方法,其代码如下。
#import "PickerViewController.h"
#define kCities @"cities"
#define kState @"state"
@interface PickerViewController () <UIPickerViewDataSource,UIPickerViewDelegate>
@property (nonatomic,retain) NSArray * arr;//接收数据;
@property (nonatomic,retain) NSArray * cityArr;//城市数据;
/// 省份
@property (nonatomic,retain) NSMutableArray * provinceArr;
@property (nonatomic,retain) UIPickerView * pickerView;
@end
@implementation PickerViewController
- (void)dealloc{
[_arr release];
[_cityArr release];
[_provinceArr release];
[_pickerView release];
[super dealloc];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self initData];
self.pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0,100,375,200)];
//显示内容;
self.pickerView.showsSelectionIndicator = YES;
//刷新某个滚轮的内容;
//[self.pickerView reloadComponent:1];
//获得选中滚轮当前所在行;
// NSInteger row = [self.pickerView selectedRowInComponent:0];
[self.view addSubview:self.pickerView];
[_pickerView release];
//指定代理;
self.pickerView.delegate = self;
self.pickerView.dataSource = self;
UIButton * btn = [UIButton buttonWithType:UIButtonTypeSystem ];
btn.frame = CGRectMake(100,400,175,40);
btn.backgroundColor = [UIColor orangeColor];
[btn addTarget:self action:@selector(handleBtn:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
//更新数据库;
- (void)initData{
//获取索引;
NSString * filePath = [[NSBundle mainBundle] pathForResource:@"city" ofType:@"plist"];
//接收数据;
self.arr = [NSArray arrayWithContentsOfFile:filePath];
//获得省份的数据;
self.provinceArr = [NSMutableArray arrayWithCapacity:1];
for (NSDictionary * dic in _arr) {
//获取省份的信息;
NSString * province = dic[kState];
[self.provinceArr addObject:province];
}
//默认显示第一个省得内容;
self.cityArr = self.arr[0][kCities];
}
- (void)handleBtn:(UIButton *)sender{
}
#pragma mark -- UIPickerView DataSource;
//返回滚轮的个数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 2;
}
//返回每个滚轮的行数;
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return (0 == component) ? self.provinceArr.count : self.cityArr.count;
}
#pragma mark -- UIPickerView Delegate
//设置每一行的内容;
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return (0 == component) ? self.provinceArr[row] : self.cityArr[row];
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if (0 == component) {
//获取第一个滚轮操作的行
NSInteger row = [self.pickerView selectedRowInComponent:0];
//获取市区的数据;
self.cityArr = self.arr[row][kCities];
//更新第二个滚轮的信息;
[self.pickerView reloadComponent:1];
//每次滚动时,让第二个滚轮选中第一行的内容;
[self.pickerView selectRow:0 inComponent:1 animated:YES];
}
}
下面是看别人的 一个游戏的实现 -----以供参考
相互依赖的多列选择器
虽然是一个两列的 UIPickerView 控件,但该控件的两列基本没有任何关系,选择第一列的作者时,第二列的图书不会动态更新——在某些情况下,这是允许的。但在某些情况下,我们需要第二列的列表项依赖第一列的选择,即当第一列选择作者时,第二列只显示该作者的图书。
为了让第二列能根据第一列的选择动态加载,程序需要用户选择第一列的事件,并根据该事件动态加载第二列的数据,然后强制重新加载 UIDatePicker 的第二列列表项。
下面创建一个相互依赖的多列选择器,首先创建一个 Single View Application ,使用 Interface Builder 打开应用的界面设计文件,并将一个 UIPickerView 拖入界面设计文件中,为在程序中访问该控件,需要将该控件绑定到 picker IBOutlet 属性。
接下来开始修改控制器类,本例使用控制器类作为 UIPickerView 的 dataSource 和 delegate ,因此,程序需要让控制器类实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议。
修改控制器类的实现代码,主要就是实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议中的必要方法,其代码如下。
复制代码
|
上面控制器类的实现部分与前一个示例中控制器类的实现部分大致相同,关键就是程序中的粗体字代码。本程序采用了 NSDictionary 分别保存 NSPickerView 控件中的两列数据, NSDictionary 的所有 key 组成的集合作为第 1 列的数据,当用户选中第一列的某个作者后,程序取出 NSDictionary 中该作者对应的图书集合作为第二列的数据。这就可以让第二列数据随第一列的选择动态改变。
前面示例看到的所有列表项都是文字形式,实际上, UIPickerView 允许开发者对列表项进行任意定制。开发者只要实现 UIPickerViewDelegate 协议中的 -pickerView:viewForRow:forComponent: reusingView: 方法即可,该方法返回的 UIView 将作为 UIPickerView 指定列和列表项的视图控件。
实例:“老虎机 ”游戏
下面以一个简单的“老虎机”游戏实例来示范自定义选择器视图的用法。
首先创建一个 Single View Application ,使用 Interface Builder 打开应用的界面设计文件,并将一个 UIPickerView 拖入界面设计文件中,再将一个 UIImageView 和一个 UIButton 拖入应用界面中,然后将这三个控件摆放整齐。为了在程序中访问这三个控件,分别将它们绑定到 picker 、 image 、 startBn 这三个 IBAction 属性。除此之外,程序还需要响应按钮的点击事件,因此为该按钮控件的 Touch Up Inside 事件绑定 clicked: 事件处理方法。
提示:
“老虎机”游戏的列表项都是图标,则需要为该实例准备一些图标——读者既可用本实例提供的图标,也可用自己选择的图标,但图标不要太大,以小于 60 像素× 60 像素为宜,将这些图标拖入应用中即可。
接下来开始修改控制器类,本例使用控制器类作为 UIPickerView 的 dataSource 和 delegate ,因此程序需要让控制器类实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议。除此之外,程序需要分别为 UIPickerView 的 5 列准备数据,因此程序在控制器类的接口部分定义了 5 个 NSArray 属性,其代码如下。
程序清单: codes/10/10.12/CustomPicker/CustomPicker/FKViewController.h
复制代码
|
然后修改该控制器类的实现部分,主要就是实现 UIPickerViewDataSource 、 UIPickerViewDelegate 两个协议中的必要方法,其代码如下。
复制代码
|
上面程序中为 UIPickerView 实现自定义列表项的关键就是第一段粗体字代码,该方法返回一个 UIImageView 作为各列的列表项控件。因此,该示例中 UIPickerView 所包含的各列的列表项都是 UIImageView 控件。
接下来的两行粗体字代码负责生成一个随机数,并根据生成的随机数来选中 UIPickerView 的指定列表项,这样就可让 UIPickerView 的 5 列随机选中指定的列表项——程序接下来的代码判断 5 个随机数中是否有相同的数出现过 3 次以上(意味着 UIPickerView 的 5 列中出现了 3 个以上相同的图标)——如果符合该条件,程序就延迟 0.5 秒执行 showWin 方法(该方法就是播放胜利音乐并显示胜利图标),否则就延迟 0.5 秒执行 showLose 方法(该方法显示失败图标)。
由于该程序使用 AudioToolbox 来播放音乐,因此程序还需要将 win.wav 和 crunch.wav 两个音乐文件拖入项目中。除此之外, iOS 项目默认是不带 AudioToolbox 库的,因此需要手动添加 AudioToolbox 库,为 iOS 项目添加指定库的步骤如下。
① 在项目导航面板中单击指定项目对应的图标。
② 选中中间编辑区域左侧的 TARGETS 下面的应用,如图 10.50 所示。
图 10.50 添加库
③ 选择编辑窗口上方的 Build Phases 标签,单击 Link Binary With Libraries 旁边的三角符号,即可展开该项目当前包含的所有库,如图 10.51 所示。
图 10.50 添加库
④ 单击图 10.51 所示窗口中“添加库”的“ + ”图标,系统将会显示如图 10.52 所示的库列表。
⑤ 在图 10.52 所示的对话框中选中需要添加的库(也可通过上面的搜索框进行搜索),单击“ Add ”按钮即可完成添加。
图 10.52 选择需要添加的库
按上面所示步骤为该项目添加 AudioToolbox 库,然后编译、运行该程序,即可通过单击程序界面上的按钮开始游戏,游戏界面如图 10.53 所示。
图 10.53 自定义 UIPickerView 实现老虎机