转自:http://blog.csdn.net/nono_love_lilith/article/details/7527794
Date Picker控件和Picker View控件其实也是算比较常用到视图。
以下根据红柚子上得几个例子:
分别从(日期选取器)Date Picker ——>单部件选取器——>多部件选取器——>依赖组建选取器。
这边我们不是一步步从创建一个项目开始,毕竟有过前面两三次的实践后,
对于如何选择性的创建一个最合适的应用基础模板已经很简单了。
这边为了方便视图切换,我们用了前面用到过的TabBarController视图控制器。
下面是对以上4种分别举个小例子
一:日期选取器

就是很简单一个日期组建,触摸滚轮可以选取时间,点击确认弹出你选中得时间。
(不过不知道什么情况,感觉有貌似我这个显示怎么出了个8小时的时差~~,不知道是模拟器还是哪边要设置,比如Android会有个设置系统时区什么的)。
我们先不管这个,这几界面就很简单。我们就看到一个datePicker控件和一个确认控件么(这个都知道在xib文件右边拖拽进来吧)
-
-
-
-
-
-
-
-
- #import <UIKit/UIKit.h>
-
- @interface NonoFirstViewController : UIViewController
- {
- UIDatePicker *datePicker;
-
- }
- @property(nonatomic, retain) IBOutlet UIDatePicker *datePicker;
- -(IBAction)buttonPressed:(id)sender;
- @end
头文件我们定义了这一个输出口和一个按钮事件
-
-
-
-
-
-
-
- #import "NonoFirstViewController.h"
-
- @implementation NonoFirstViewController
- @synthesize datePicker;
- -(IBAction)buttonPressed:(id)sender
- {
- NSDate * selected = [self.datePicker date];
- NSString *date = [[NSString alloc] initWithFormat:@"你选择了:%@",selected];
- UIAlertView * alterView = [[UIAlertView alloc] initWithTitle:@"时间提示" message:date delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];
- [alterView show];
-
- }
-
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- NSDate *now = [[NSDate alloc] init];
- [datePicker setDate:now animated:YES];
-
- }
-
-
-
- @end
实现文件也很简单,基本没什么说的,因为这个控件我们跳进datePicker的头文件,发现其实他就是一种pickerView的封装实现。
对于我们来说,使用范围就比较局限性。看他的类名我们就知道了。
因此很多时候,我们都会需要自定义Picker View
二:Picker View组件

这个就是一个单部件的picker View。
根据我们的思路或是一些开发经验。
看到这么一个东西,大致可以知道:第一,有个展示界面(也就是我们拖进去的PickerView)
第二,需要有填充这个界面的数据源
第三,需要一个我们对该控件相关操作的控制者。
有过Android开发的朋友也该很容易联想到一个东西,就是Adapter,适配器。
其实ios这个也是差不多。
这边提一点,其实IOS这种适配模式等你接触后,就会恍然大悟的发现,就这么一个模式。
一个视图,实现一个数据源协议,实现一个(控制器代理)。
基本所有类似组建得表现形式和操作都是这三者的结合。(MVC模式啊,代理模式啊什么,这算吧,也挺形象了)
废话不多说,先看下头文件
-
-
-
-
-
-
-
-
- #import <UIKit/UIKit.h>
-
- @interface NonoSecondViewController : UIViewController
- <UIPickerViewDelegate,UIPickerViewDataSource>
- {
- UIPickerView * pickerView;
- NSArray *pickerData;
- }
- @property(nonatomic,retain) NSArray *pickerData;
- @property(nonatomic, retain) IBOutlet UIPickerView *pickerView;
- -(IBAction)buttonPressed:(id)sender;
-
- @end
申明了需要实现的两个 <UIPickerViewDelegate,UIPickerViewDataSource>
就是我们上面提到的。
多了一个属性申明 一个数组。等会用于存放数据源。
-
-
-
-
-
-
-
-
- #import "NonoSecondViewController.h"
-
- @implementation NonoSecondViewController
- @synthesize pickerData;
- @synthesize pickerView;
-
-
- -(void)buttonPressed:(id)sender
- {
- NSInteger row = [pickerView selectedRowInComponent:(0)];
- NSString *selected = [pickerData objectAtIndex:row];
- NSString *title = [[NSString alloc] initWithFormat:@"你选择的:%@!",selected];
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:title delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
- [alert show];
-
- }
-
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
-
- }
- return self;
- }
-
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- NSArray *array = [[NSArray alloc] initWithObjects:@"陈凯", @"至尊宝",@"菩提老祖",@"二当家",@"紫霞仙子",@"蜗牛",nil];
- self.pickerData = array;
-
-
-
- }
-
- - (void)viewDidUnload
- {
- [super viewDidUnload];
- self.pickerData = nil;
- self.pickerView = nil;
-
-
- }
-
- - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
- {
- return (interfaceOrientation == UIInterfaceOrientationPortrait);
- }
-
- #pragma mark -
- #pragma mark Picker Data Source Methods
- - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
- {
- return (1);
- }
- - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
- {
- return [pickerData count];
- }
- #pragma mark Picker Delegate Methods
-
- - (NSString *)pickerView:(UIPickerView *)pickerView
- titleForRow:(NSInteger)row
- forComponent:(NSInteger)component
- {
- return [pickerData objectAtIndex:row];
- }
-
- @end
主要看下#pragma mark下得三个方法(pragma干嘛使,其实也不太明白,目前知道感觉就如一个标记东西,不写其实也没关系,写了我们可以看得比较明白
,以下使我们实现的协议方法。述说貌似对其有个更好的解释,大家可以google或是看书。)
首先,必须实现的两个数据源协议中的方法。
第一个:- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return (1);//返回在这个pickerView中得部件个数
}
这是什么意思呢?以我的简单理解说下吧。
我们整个视图是一个PickerView,里面可以有单个货多个部件(什么意思?看上面两个截图,
DatePicker中4个部件,至尊宝中就是一个部件)
好吧,应该了解了。这个方法得返回值就是返回你所要显示得部件个数。
这边我们知道,我们就一个部件,也只需显示一个部件。
第二个:- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return [pickerData count];
}
返回每个部件中要显示数据的条数。说白了就是返回你要填充这个部件的数据源中数据元素的个数,这边就是数组的大小么。
以上两个是数据源的协议方法实现,下面这个是pickerView委托中方法的实现。
当然,这个委托协议中的我们能看到很多方法,但是是可选的,可以根据我们得需要来实现。
但是上面代码也说了,虽然可选,但是基本都会要实现这个方法。
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
return [pickerData objectAtIndex:row];
}
因为我们知道,数据源协议两个方法只不过是和我们得视图做了一个关联,
如何把数据显示出来,就靠这个方法了。
单个部件的基本就是这么简单。
三:多部件控件以及依赖组件
这两个就一起说算了,因为差不多。

两个滚轮,就是多部件组件形式(当然你可以更多)。
组建的相互依赖,也很简单,既当我我第一个滚轮滚到鸟类时,第二个滚轮中得数据是鸟;
鱼儿的时候是鲤鱼鲨鱼。前者就像一个父节点一样。
下面我来定义头文件
-
-
-
-
-
-
- #import <UIKit/UIKit.h>
-
- #define mFather 0
- #define mChilder 1
-
- @interface NonoDependentOnViewController : UIViewController<UIPickerViewDelegate,UIPickerViewDataSource>
- {
- UIPickerView *dependentPickerView;
- NSArray *fatherArray;
- NSArray *childeArray;
- NSDictionary *dictionary;
- }
-
- @property(retain ,nonatomic) IBOutlet UIPickerView *dependentPickerView;
- @property(retain,nonatomic) NSArray *fatherArray;
- @property(retain,nonatomic) NSArray *childerArray;
- @property(retain, nonatomic) NSDictionary *dictionary;
-
- - (IBAction)buttonPressed:(id)sender;
-
- @end
几个属性,fatherArray就是用于存放第一个滚轮的数据源数组(比如鱼儿,鸟类),childerArray用于存放第二个滚轮的数据源组
实现文件
-
-
-
-
-
-
-
-
- #import "NonoDependentOnViewController.h"
-
-
- @implementation NonoDependentOnViewController
- @synthesize dependentPickerView;
- @synthesize fatherArray;
- @synthesize childerArray;
- @synthesize dictionary;
-
- - (IBAction)buttonPressed:(id)sender
- {
- <span style="white-space:pre"> </span>。。。。
- }
-
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
- NSBundle *bundle = [NSBundle mainBundle];
- NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"];
- NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path];
- self.dictionary = dic;
-
- NSArray *rootArray = [self.dictionary allKeys];
- NSArray *root = [rootArray sortedArrayUsingSelector:@selector(compare:)];
- self.fatherArray = root;
-
- NSString *fatherSec = [self.fatherArray objectAtIndex:0];
- NSArray *array = [self.dictionary objectForKey:fatherSec];
- self.childerArray = array;
-
-
- }
-
- #pragma mark -
-
-
- - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
- {
- return 2;
- }
-
-
- - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
- {
- if (component == mFather) {
- return [self.fatherArray count];
- }else {
- return [self.childerArray count];
- }
- }
-
-
-
-
- - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
- {
- if(component == mFather){
- return [self.fatherArray objectAtIndex:row];
- }else {
- return [self.childerArray objectAtIndex:row];
- }
- }
-
-
- - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
- {
- if (component == mFather) {
- NSString *string = [self.fatherArray objectAtIndex:row];
- NSArray *array = [self.dictionary objectForKey:string];
- self.childerArray = array;
- [dependentPickerView selectRow:0 inComponent:mChilder animated:YES];
- [dependentPickerView reloadComponent:mChilder];
- }
-
- NSLog(@"触发依赖");
- }
-
- - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
- {
- if(component == mFather)
- return (100);
- return 200;
- }
-
- @end
(几个默认的我们这边不提及到得方法我delete掉了)
这边我们涉及下一个小的api知识,就是用plist文件存储数据。这个以后也会是常用的。
基本步骤是:1.新定义一个plist文件
2.打开plist文件自定义一些数据源
大致界面就是:

- NSBundle *bundle = [NSBundle mainBundle];
- NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"];
- NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path];
- self.dictionary = dic;
其实就是读取了这个一个文件,后一NSDictionary的对象保存起来。因为我们以xml形式打开这个plist文件
会发现,这货最外层得标签就是一个<dict>
- <?xml version="1.0" encoding="UTF-8"?>
- <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
- <plist version="1.0">
- <dict>
- <key>鱼儿</key>
- <array>
- <string>鲤鱼</string>
- <string>鲨鱼</string>
- </array>
- <key>鸟类</key>
- <array>
- <string>大鸟</string>
- <string>小鸟</string>
- </array>
- </dict>
- </plist>
allkeys后返回所有key对应得value放入一个数组,书本上又对数组做了下排序操作。
默认我们选取了索引为0的父源,以及对应的子源。
然后继续看数据源协议得两个方法,略微有点变化
第一个不说了,返回部件数为2;
第二个// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == mFather) {
return [self.fatherArray count]; //如果是父部件,返回填充父部件数据源个数
}else {
return [self.childerArray count];//子部件。。。。。。
}
}
同理的,对于pickerView委托方法中这个方法也很好理解
//显示在view上
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component == mFather){
return [self.fatherArray objectAtIndex:row];
}else {
return [self.childerArray objectAtIndex:row];
}
}
最主要是这个委托方法实现,也是依赖组件的核心
-
- - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
- {
- if (component == mFather) {
- NSString *string = [self.fatherArray objectAtIndex:row];
- NSArray *array = [self.dictionary objectForKey:string];
- self.childerArray = array;
- [dependentPickerView selectRow:0 inComponent:mChilder animated:YES];
- [dependentPickerView reloadComponent:mChilder];
- }
-
- NSLog(@"触发依赖");
- }
看方法名我们可以知道是部件上某条数据(row)被选中后。可以做出相应得操作。
这边我们知道,我们选中了不同得父源后,需要显示相应的子源。
因此我们可以做一些如上得代码操作。
好了。选取期组件初步基本就这些。
这个列子还是好久前写的,因此大伙看到没有 release呵呵,因为我那会创建还是用得ARC。
说简单点,核心就三点:
一个pickerView,一个数据源协议,一个委托协议。
完